Logo Search packages:      
Sourcecode: aaphoto version File versions  Download package

aargb.c

/*-----------------------------------------------------------------------
    This file is part of aaPhoto.

    aaPhoto is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    aaPhoto is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
------------------------------------------------------------------------*/





// ---------------------------------------------------
// ----------- Auto Adjust RGB Plug-in ---------------
// ----------- András Horváth (C) 2006-2010 ----------
// ----------- Hungary, http://log69.com -------------
// ---------------------------------------------------

/*

aaRGB Changelog:
------------------
2009/10/18 - aaRGB v0.60 - gamma handling of the lighter colors removed from the two-pole gamma computing
                           by setting the gamma_interval_high from 0.9 to 1
                           it proved to be inefficient
2009/04/05 - aaRGB v0.59 - some more code cleanup
2009/02/22 - aaRGB v0.58 - code cleanup
2007/08/11 - aaRGB v0.57 - improved black and white point analyzing
                           from now they won't be scaled to perfect black and white but to their darkest
                           and brightest color that have maximum saturation -with this, overexposure problem fixed
                         - improved saturation algorithm with full floating point computing and HSL conversion
                           with this, oversaturated colors problem fixed
                         - expanded image information display with color balance circle for testing (--test switch)
                         - removed text information from test display (--test switch)
2007/06/21 - aaRGB v0.56 - expanded functionality with "apply only on selection" to apply the changes only on the selected area
2007/04/03 - aaRGB v0.55 - maximizing saturation limit with a predefined constant to avoid overexposure on saturation
                           when reconverting the same image
2007/04/01 - aaRGB v0.54 - new two-pole gamma computing
                         - new saturation compensation
2007/03/29 - aaRGB v0.53 - improved contrast computing to avoid underexposure
2007/02/25 - aaRGB v0.52 - improved image information display for testing (--test switch)
2007/02/16 - aaRGB v0.51 - improved average RGB color computing for more accurate color balance calibration
2007/01/04 - aaRGB v0.49 - stable working version with gamma handling and more clever image analyzing
2006/08/29 - aaRGB project begun...

aaRGB end of Changelog.

*/


// Auto adjusting contrast, color balance, gamma level of image and saturation


// A kontraszt állításra azért van szükség, mert egy nem megfelelõen beállított
// képnek a legsötétebb színe általában nem megfelelõen sötét,
// illetve a legvilágosabb színe nem megfelelõen világos, és ez fátyolos hatást
// eredményez a képen, vagyis kevésbé látható

// A színegyensúly állításra azért van szükség, mert a képnek a legvilágosabb
// része nem tökéletes fehér, illetve a legsötétebb része nem tökéletes fekete,
// hanem valamilyen más szín irányába van eltolódva
// erre a kép elõállításának technológiája is hatással van

// Az eljárás feltételezi, hogy a képen létezik olyan részlet, aminek a
// valóságban elvileg feketének (nagyon sötétnek)
// illetve fehérnek (nagyon világosnak) kellene lennie,
// erre épül az automatikus kontraszt és színegyensúly beállítása.

// A gamma állítással lehet a kép egészének sötétségét illetve világosságát
// beállítani (vagyis az átlag fényerejét)
// Ez a beállítás pedig arra törekedik, hogy a kép összes átlag fényereje
// egy meghatározott világosságú legyen de mindezt úgy, hogy közben a legsötétebb
// és legvilágosabb fényerejû érték ne változzon
// Ez hatványra emeléssel történik egy [0..1] intervallumon.

// A színtelítettség állításánál felerősítésre kerül az összes szín egy
// súlyozással megállapított értékkel.





#include <math.h>


// -------------------------
// ----- SIGN FUNCTION -----
// -------------------------

int sgn(double x)
{
    if (x <  0) { return -1; }
    if (x >  0) { return  1; }
//  if x is 0 then return 0
    return 0;
}



// --------------------------------
// ----- RGB - HSL CONVERSION -----
// --------------------------------

void RGB_TO_HSL(double R, double G, double B, double *H1, double *S1, double *L1)
{
    if (R < 0) { R = 0; } if (R > 1) { R = 1; }
    if (G < 0) { G = 0; } if (G > 1) { G = 1; }
    if (B < 0) { B = 0; } if (B > 1) { B = 1; }

    double H = 0;
    double S = 0;
    double L = 0;

    L = (R + G + B) / 3;

    // Az 'S' színtelítettségi érték számításához megnézzük,
    // hogy milyen aránnyal lehetne maximálisan az RGB hármast
    // úgy "széthúzni" a határukig, hogy közben az 'L' és 'H' érték nem változik
    // LN = Legnagyobb, LK = Legkisebb

    double LN, LK, LNX, LKX;
    LN = R;
    if (LN < G) { LN = G; }
    if (LN < B) { LN = B; }
    LK = R;
    if (LK > G) { LK = G; }
    if (LK > B) { LK = B; }
    if (LN == LK) { S = 0; H = 0; }
    else {

        if ((LN < 1) && (LK > 0)) {
            // L cannot be either 0 or 1 here
            LKX = (L - LK) / L;
            LNX = (LN - L) / (1 - L);
            S = LNX;
            if (LKX >= LNX) { S = LKX; }
        }
        else { S = 1; }

        // A 'H' szín értékhez széthúzzuk az RGB hármast maximumig,
        // és így 6 részre bontható eset leketkezik.

        double R2, G2, B2;
        LN = LN - LK;
        R2 = (R - LK) / LN;
        G2 = (G - LK) / LN;
        B2 = (B - LK) / LN;

        if ((R2 == 1) && (G2 <  1) && (G2 >= 0) && (B2 == 0))  { H = (  0 +    G2  * 60) / 360; }
        if ((G2 == 1) && (R2 <= 1) && (R2 >  0) && (B2 == 0))  { H = ( 60 + (1-R2) * 60) / 360; }
        if ((G2 == 1) && (B2 <  1) && (B2 >= 0) && (R2 == 0))  { H = (120 +    B2  * 60) / 360; }
        if ((B2 == 1) && (G2 <= 1) && (G2 >  0) && (R2 == 0))  { H = (180 + (1-G2) * 60) / 360; }
        if ((B2 == 1) && (R2 <  1) && (R2 >= 0) && (G2 == 0))  { H = (240 +    R2  * 60) / 360; }
        if ((R2 == 1) && (B2 <= 1) && (B2 >  0) && (G2 == 0))  { H = (300 + (1-B2) * 60) / 360; }

        if (H == 1) { H = 0; }
    }

    *H1 = H; *S1 = S; *L1 = L;

}



void HSL_TO_RGB(double H, double S, double L, double *R1, double *G1, double *B1)
{
    if (H < 0) { H = 0; } if (H > 1) { H = 1; }
    if (S < 0) { S = 0; } if (S > 1) { S = 1; }
    if (L < 0) { L = 0; } if (L > 1) { L = 1; }

    double R = 0;
    double G = 0;
    double B = 0;

    if (L == 0) { R = 0; G = 0; B = 0; }
    else {
        if (L == 1) { R = 1; G = 1; B = 1; }
        else {
            // 'H' érték alapján való beállítás
            int deg;
            double mul;
            if (H == 1) { H = 0; }
            deg = H * 6;
            mul = H * 6 - deg;

            switch (deg) {
                case 0:
                    R = 1; G = mul;   B = 0; break;
                case 1:
                    G = 1; R = 1-mul; B = 0; break;
                case 2:
                    G = 1; B = mul;   R = 0; break;
                case 3:
                    B = 1; G = 1-mul; R = 0; break;
                case 4:
                    B = 1; R = mul;   G = 0; break;
                case 5:
                    R = 1; B = 1-mul; G = 0; break;
            }

            // 'L' érték alapján való skálázás az RGB mezőben
            double L2, templ;
            L2 = (R + G + B) / 3;
            if (L > L2) {
                templ = (1-L) / (1-L2);
                R = 1 - (1-R) * templ;
                G = 1 - (1-G) * templ;
                B = 1 - (1-B) * templ;
            }
            else {
                templ = L / L2;
                R = R * templ;
                G = G * templ;
                B = B * templ;
            }

            // 'S' érték alapján való skálázás az RGB mezőben
            if (R > L) { R = L + (R-L) * S; } else { R = L - (L-R) * S; }
            if (G > L) { G = L + (G-L) * S; } else { G = L - (L-G) * S; }
            if (B > L) { B = L + (B-L) * S; } else { B = L - (L-B) * S; }
        }
    }

    *R1 = R; *G1 = G; *B1 = B;

}



// ------------------------------------------------------------------------------

void 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)
{


// ------------------------------------------------------------------------------
// Global variables for the procedure
// ------------------------------------------------------------------------------
// Globális változók deklarálása
// Megjegyzésként, hogy tömbök felhasznált elemeinek száma deklarálásnál
// az értéknek 1-gyel többnek kell lennie

      double cont_max;
      double gamma_max;
      double gamma_interval_low;
      double gamma_interval_high;
      double satur_max;

      double gamma_weight_low_all;
      double gamma_weight_high_all;
      double gamma_weight_low;
      double gamma_weight_high;
      double gamma_low;
      double gamma_high;

      long hist1[256];
      long hist2[256];
      long hist3[256];
      long hist_min;
      long hist_max;
      double hist_avg;
      long hist_min_test;
      long hist_max_test;
      double hist_avg_test;

      long hist_satur[256];
      double hist_satur_avg;
      double hist_satur_low;
      double hist_satur_ok;

      double temp1, temp2, temp3;
      long flag1;
      long bw, bh;
      long x, y;
      long i1, i2, i3;

      long col_r, col_g, col_b;
      double col_r2, col_g2, col_b2;
      unsigned long col_r3[256], col_g3[256], col_b3[256];

      double H, S, L;

      double wp, bp;
      double wp_end, bp_end;
      double wp_r, wp_g, wp_b;
      double bp_r, bp_g, bp_b;
      double wp_r_end, wp_g_end, wp_b_end;
      double bp_r_end, bp_g_end, bp_b_end;

      long cc;
      long addr, addr2;
      long addr_offset;

#ifndef NO_MATH

      long col;
      long xm, ym;
      long color_black =        0x00000000;
      long color_green =        0x0000ff00;
      long color_green_dark =   0x00008000;
      long color_yellow =       0x00ffff00;
      long color_brown =        0x00808000;
      long color_red =          0x00ff0000;
      long color_blue =         0x000080ff;

#endif



// ------------------------------------------------------------------------------
// Initialization and constants for the contrast and gamma (0...1)
// ------------------------------------------------------------------------------
// Kezdõ értékek és konstansok megadása a kontraszt és gamma mûveletekhez

// Kontraszt konstans megadása: megadja, hogy mekkora lehet az automata
// kontraszt állítás maximum értéke (0...1-ig terjedhet az értéke),
// alapértelmezett = 0.1
// Gamma konstans megadása: megadja, hogy mekkora lehet az automatikus
// gamma állítás maximum értéke (1...10-ig ajánlott),
// alapértelmezett = 1.5

// Gamma állításhoz a maximum elõfordulás értékének megadása (occur_max),
// amely megadja, hogy a gamma érték számításánál ha ennél kisebb az
// elõfordulása a nagy mértékben elõforduló színeknek, akkor kihagyjuk õket a
// számításból, vagyis a nagy mértékben elõforduló színeket azért nem vesszük
// be a számításba, mert inkább a részletek látszódjanak jól,
// vagyis a részletekhez legyen inkább kiszámolva a megfelelõ fényerõ


// ------------------------------
// Konstans értékek beállítása
// ------------------------------
    // maximális kontraszt mértéke (0..1)
    cont_max = 0.1;
    // maximális gamma korrekció mértéke (1..10)
    gamma_max = 1.5;

    gamma_interval_low = 0.333;
    // gamma_interval_mid = 0.5;
    gamma_interval_high = 1;

    // maximális színtelítettség mértéke (0..1)
    satur_max = 0.333;

    bw = image_width;
    bh = image_height;

    // Kijelölt területhez a koordináták határértékeinek vizsgálata
    // és megfelelõ beállítása
    // A kijelölés célja, hogy egy meghatározott képrészletet szeretnénk jól
    // láthatóvá tenni (nem pedig az egészet arányaiban)

    // a szélesség konvertálása abszolút koordinátává, jelenleg nem él
    // x2 = x1 + x2 - 1;
    // y2 = y1 + y2 - 1;

    if (x1 < 0) { x1 = 0; }
    if (x2 < 0) { x2 = 0; }
    if (y1 < 0) { y1 = 0; }
    if (y2 < 0) { y2 = 0; }
    if (x1 > bw-1) { x1 = bw-1; }
    if (x2 > bw-1) { x2 = bw-1; }
    if (y1 > bh-1) { y1 = bh-1; }
    if (y2 > bh-1) { y2 = bh-1; }
    // A DIB formátum 4-byte-os igazításához az eltolás értékének kiszámítása
    // Normál tömbnél erre nincs szükség, ekkor a format_flag értéke = 0
    // egyébként a DIB formátumú tömb függõlegesen fordított sorokat tartalmaz,
    // és a sorvégek 4 byte-tal vannak igazítva
    addr_offset = 0;
    // Format = 0 --> NORMAL 3 byte RGB data in array
    // Format = 1 --> DIB data format in array
    // Format = 2 --> BMP data format in array
    if ((format_flag == 1) || (format_flag == 2)){
        y1 = bh - 1 - y1;
        y2 = bh - 1 - y2;
        addr_offset = bw * 3 - 4 * (bw * 3 / 4);
        if (addr_offset != 0) addr_offset = 4 - addr_offset;
    }
    // Kijelölés koordinátáinak felcserélése, ha nem jó sorrendben adták meg,
    // vagyis a bal felsõ sarok az x1 és y1, a jobb alsó pedig az x2 és y2
    if (x1 > x2) { i1 = x1; x1 = x2; x2 = i1; }
    if (y1 > y2) { i1 = y1; y1 = y2; y2 = i1; }


// ------------------------------------------------------------------------------
// Create Histogram and average RGB colors for the Image
// ------------------------------------------------------------------------------
// Hisztogram generálása a kép színeibõl, ami a kép feényerõ eloszlását adja meg
// plusz a színegyensúly beállításához az egy fényerejû színek átlag RGB
// értékeinek letárolása, megelõlegezve egy késõbbi rutin munkáját

// A kép minden egyes pontjának átlag fényereje (szürkéje) bekerül egy
// 256 elemû tömbbe, ahol a fényerejük értéke az azonos indexû elem értékét
// 1-gyel növeli

// Így ez a hisztogram tömb pontos leírást ad a feketétõl a fehérig terjedõ
// színskálájáról a képnek

    for (i1=0; i1<=255; i1++){
        hist1[i1] = 0;
        hist2[i1] = 0;
        hist3[i1] = 0;
        hist_satur[i1] = 0;
        col_r3[i1] = 0;
        col_g3[i1] = 0;
        col_b3[i1] = 0;
    }
    for (y=0; y<=bh-1; y++){
        addr2 = y * bw * 3 + y * addr_offset;
        for (x=0; x<=bw-1; x++){
            if (x >= x1 &&
                x <= x2 &&
                y >= y1 &&
                y <= y2) {
                addr = addr2 + x * 3;
                col_r = image_buffer[addr + 0];
                col_g = image_buffer[addr + 1];
                col_b = image_buffer[addr + 2];
                cc = (col_r + col_g + col_b) / 3;
                // szürke hisztogramm
                hist1[cc] = hist1[cc] + 1;
                // Átlag RGB értékek letárolása a fekete és fehér pont
                // átlag RGB-jének későbbi megállapításához
                col_r3[cc] = col_r3[cc] + col_r;
                col_g3[cc] = col_g3[cc] + col_g;
                col_b3[cc] = col_b3[cc] + col_b;
            }
        }
    }


// ------------------------------------------------------------------------------
// Start analyzing to find the White and Black points
// ------------------------------------------------------------------------------
// Az automata kontraszt beállításához a Fekete és Fehér pont megállapítása

// A hisztogram bal és jobb oldaláról elkezdjük beolvasni a szürke értékek
// nagyságát és addig olvassuk be, amíg az nem nagyobb egy elõre meghatározott
// értéknél, ekkor megkapjuk a fekete és fehér pont nagyságát

// Ez az elõre meghatározott érték a kontraszt konstans és a hisztogram
// összes tömbeleme átlagának a szorzata
// Az átlag szorzat egyensúlyt teremt a határérték elérésénél, mert egyébként
// ha ez az érték mondjuk a hisztogram maximum értéke lenne, akkor
// drasztikus kontraszt túlállítás jellemezné a funkciót

// Vagyis ez az érték azt adja meg, hogy a kép átlag fényerejének hány
// százaléka az az érték, amely a továbbiakban megadja, hogy az ekkora
// százalék alatt található feketék és fehérek lesznek kihúzva zéróig

    hist_min = bw * bh;
    hist_max = 0;
    hist_avg = 0;

    // Átlag fényerõ kiszámítása
    // A maximum és minimum érték számítása csak tesztelési céllal él,
    // nem számít kirtikus idõtényezõnek

    for (i1=0; i1<=255; i1++){
        temp1 = hist1[i1];
        if (hist_min > (long)temp1){ hist_min = (long)temp1; }
        if (hist_max < (long)temp1){ hist_max = (long)temp1; }
        hist_avg = hist_avg + temp1;
    }
    hist_avg = hist_avg / 256;

    hist_min_test = hist_min;
    hist_max_test = hist_max;
    hist_avg_test = hist_avg;
    temp1 = cont_max * hist_avg;

    bp = 255;
    flag1 = 0;
    for (i1=0; i1<=255; i1++){
        if (flag1 == 0){
            if (hist1[i1] >= temp1){
                flag1 = 1;
                bp = i1;
            }
        }
    }
    wp = 0;
    flag1 = 0;
    for (i1=255; i1>=0; i1--){
        if (flag1 == 0){
            if (hist1[i1] >= temp1){
                flag1 = 1;
                wp = i1;
            }
        }
    }

    // Határértékek beállítása és korrekciója
    if (bp > wp){
        i1 = wp;
        wp = bp;
        bp = i1;
    }
    if (bp == wp){
       bp = bp - 1;
       wp = wp + 1;
    }
    if (bp < 0){ bp = 0; }
    if (bp >= 255){ bp = 254; }
    if (wp > 255){ wp = 255; }
    if (wp <= 0){ wp = 1; }

    bp = bp / 255;
    wp = wp / 255;



// ------------------------------------------------------------------------------
// Get the average RGB values for the White and Black points
// ------------------------------------------------------------------------------
// A színegyensúly beállításához az átlag RGB értékek kiszámítása
// a fekete és fehér pont értéke alapján

// Itt keletkezik egy átlag RGB érték a fekete és fehér pontokhoz egyaránt
// Ez az érték azt adja meg, hogy az automatikus kontraszt állításakor
// minden egyes szín milyen irányba torzul lefelé (fekete pont RGB átlaga)
// és felfelé (fehér pont RGB átlaga)

// A fehér pont feletti összes szín átlagának RGB-je lesz a viszonyítási pont
// a fehér írányába való torzításhoz,
// vagyis ez lesz kihúzva a tökéletes fehérbe

// Ez valóságban a kép színegyensúlyát állítja be megfelelõen úgy, hogy a
// levágandó mértékû fehérek színátlaga lesz a tökéletes fehér,
// ezért ha ezek átlaga nem tökéletes fehér, akkor az ettõl eltérõ nagyságot
// minden színnél arányosan el kell tolni a tökéletes fehér irányába,
// ugyanez a fekete estében

    bp_r = 0;
    bp_g = 0;
    bp_b = 0;
    wp_r = 0;
    wp_g = 0;
    wp_b = 0;

    i3 = 0;
    // fekete pont alatti összes szín RGB átlagának kiszámítása
    for (i1=(long)(bp * 255); i1>=0; i1--){
        bp_r = bp_r + col_r3[i1];
        bp_g = bp_g + col_g3[i1];
        bp_b = bp_b + col_b3[i1];
        i3 += hist1[i1];
    }
    if (i3 > 0){
        bp_r = bp_r / i3;
        bp_g = bp_g / i3;
        bp_b = bp_b / i3;
    }

    i3 = 0;
    // fehér pont feletti összes szín RGB átlagának kiszámítása
     for (i1=(long)(wp * 255); i1<=255; i1++){
        wp_r = wp_r + col_r3[i1];
        wp_g = wp_g + col_g3[i1];
        wp_b = wp_b + col_b3[i1];
        i3 += hist1[i1];
    }
    if (i3 > 0){
        wp_r = wp_r / i3;
        wp_g = wp_g / i3;
        wp_b = wp_b / i3;
    }

    // skálázás 255-ről a [0..1] intervallumra
    bp_r = bp_r / 255;
    bp_g = bp_g / 255;
    bp_b = bp_b / 255;
    wp_r = wp_r / 255;
    wp_g = wp_g / 255;
    wp_b = wp_b / 255;

    // A kapott átlag RGB érték fényerejének visszaállítása a fehér pont szintjére.
    // Mivel ugye nem csak a fehér pont fényerejével azonos színeknek kalkuláltuk ki
    // az átlag színét, hanem az attól világosabb összes színnek, ezért a kapott
    // átlag szín fényereje nagyobb vagy egyenlő lesz, mint a kiindulási fehér pont
    // ezért a korrekcióhoz visszaállítjuk az RGB érték fényerejét
    // de az R, G és B komponensek arányának a megtartásával
    // és ugyanez a fekete pont esetében
    RGB_TO_HSL (bp_r, bp_g, bp_b, &H, &S, &L);
    L = bp;
    HSL_TO_RGB (H, S, L, &bp_r, &bp_g, &bp_b);
    RGB_TO_HSL (wp_r, wp_g, wp_b, &H, &S, &L);
    L = wp;
    HSL_TO_RGB (H, S, L, &wp_r, &wp_g, &wp_b);

    // A fekete és fehér pont célpontjának kiszámítása.
    // Ez mutatja meg, hogy a fekete és fehér pont átlag RGB-jét
    // hova kell húzni úgy, hogy az RGB kockában a két csúcsot
    // összekötő 'szürke' egyenessel párhuzamosan tolva a távolsága
    // a 'szürke' egyenestől és a színiránya megmaradjon,
    // de a lehető legsötétebb- vagy legvilágosabb legyen
    //
    // Másképpen fogalmazva eltoljuk a szürke egyenes mentén addig,
    // amíg az RGB kocka falába nem ütközünk (mindkét iránynál)
    //
    // Ez  annyiban változtatás az előzőkhöz képest, hogy a fekete pontot
    // most már nem a tökéletes feketébe húzzuk, hanem az annak megfelelő
    // olyan legsötétebb pontba, ahol a maximum a színtelítettség
    // és aminek színe megegyezik a fekete pontéval,
    // ezzel a rossz színegyensúlyt és nem megfelelő kontrasztot küszöbölöm ki.

    temp3 = bp_r;
    if (temp3 > bp_g) { temp3 = bp_g; }
    if (temp3 > bp_b) { temp3 = bp_b; }
    //bp_r_end = 1 - (1 - bp_r) / (1 - temp3);
    //bp_g_end = 1 - (1 - bp_g) / (1 - temp3);
    //bp_b_end = 1 - (1 - bp_b) / (1 - temp3);
    bp_r_end = bp_r - temp3;
    bp_g_end = bp_g - temp3;
    bp_b_end = bp_b - temp3;

    temp3 = wp_r;
    if (temp3 < wp_g) { temp3 = wp_g; }
    if (temp3 < wp_b) { temp3 = wp_b; }
    if (temp3 > 0){
        wp_r_end = wp_r / temp3;
        wp_g_end = wp_g / temp3;
        wp_b_end = wp_b / temp3;
    }



// -----------------
// ---- RGB TÉR ----
// -----------------
// A teljes RGB teret egy szabályos 3D-s kocka foglalja magába,
// amelynek 1-1 éle jelenti a R, a G és a B tengelyt
// és egyik csúcsában található a tökéletes fehér szín,
// a másik (ezzel szemköti) csúcsában pedig a tökéletes fekete
// és ezt a két csúcsot összekötő egyenes tartalmazza a
// feketétől fehérig terjedő teljes szürke skálát.
// A színeltolás mértéke pedig nem más, mint az adott szín
// távolsága merőleges írányban szürke skála egyenesétől
// (amit egy 0 és 1 közötti érték jellemezhet, ahol a 0
// azt jelenti, hogy a szín szürke, vagyis az egyenesen található)
//
// -------------------------
// ---- RGB SZÍN IRÁNYA ----
// -------------------------
// A fekete és fehér pont átlag eltolási RGB értékét összehasonlítom,
// hogy megállapítsam, vajon megegyező irányban vannak-e eltolva,
// mivel ha nem jó a kép színegyensúlya, akkor feltételezem, hogy
// a kép összes színe a színegyensúly felborulását okozó tényező miatt
// megegyező irányban tolódik el. Ha nem megegyező irányba mutat
// az eltolásuk értéke, akkor feltételezem, hogy ez nem azért van,
// mert a színegyensúly felborult. Ekkor a kontraszt műveletnél nem
// alkalmazok színegyensúly kiegyenlítést (vagyis a kép színeinek
// a tökéletes fehér és tökéletes fekete irányába való RGB korrekcióját).
//
// Egy adott szín irányán az RGB kockában található pontjából kiinduló
// merőleges szakasz körülforgási szögét értem a szürke egyenesre nézve.
// Ennek értéke -180 és 180 fok közé kell hogy essen.
// Így a fekete és fehér pont átlag RGB színeinek iránya megad két szöget.
// Ennek különbsége adja meg, hogy milyen mértékkel kell színegyensúly
// kompenzációt végezni. Minél jobban egyírányba mutatnak, annál erősebb
// színkompenzáció szükséges.



// ------------------------------------------------------------------------------------
// Get RGB color directions of the White and Black points and change average RGB colors
// ------------------------------------------------------------------------------------
// Megállapítjuk a fekete és fehér pont átlag RGB értékeinek irányát
// Ez két szöget ad vissza, és ennek a különbségét vizsgáljuk,
// minél kevésbé eltérő, az átlag RGB értékeket annál jobban lecseréljük
// a tökéletes fekete és fehér értékre, így a kontraszt állításnál
// jobban keletkezik színegyensúly korrekció
//
// Mivel az irányuk egy 360˚-os szöget zár be, és az eltérő színek 60˚-onként vannak,
// ezért a 60˚-nál nagyobb eltérést teljesen különbözőnek vesszük.
// Vagyis a 60˚-nál kisebb eltérésnél toljuk csak el arányosan a fekete és
// fehér pont célpontját a tökéletes fekete és a tökéletes fehér írányába
// (vagyis egyező irány esetén teljes színkorrekció lép fel)

    RGB_TO_HSL (bp_r_end, bp_g_end, bp_b_end, &H, &S, &L);
    temp1 = H;
    RGB_TO_HSL (wp_r_end, wp_g_end, wp_b_end, &H, &S, &L);
    temp2 = H;
    temp2 = temp2 - temp1;
    if (temp2 < 0)   { temp2 = 0 - temp2; }
    if (temp2 > 0.5) { temp2 = 1 - temp2; }
    temp2 = temp2 + temp2;

    // Ezzel megvan az iránykülönbség értéke egy [0..1] intervallumon,
    // ahol a 0 a teljes egyezést mutatja
    // most az egész 'kör' hatod részét vizsgálom csak és
    // abból alakítok ki egy értéket a [0..1] intervallumon,
    // hogy majd ezzel szorozni tudjam a fekete pont fényerejét,
    // vagyis ha egyeznek az írányok, akkor tökéletes feketébe megy el
    // ugyanez a fehér pont esetében
    if (temp2 * 6 < 1) {
        temp2 = temp2 * 6;
        RGB_TO_HSL (bp_r_end, bp_g_end, bp_b_end, &H, &S, &L);
        L = L * temp2;
        HSL_TO_RGB (H, S, L, &bp_r_end, &bp_g_end, &bp_b_end);
        RGB_TO_HSL (wp_r_end, wp_g_end, wp_b_end, &H, &S, &L);
        L = 1 - (1 - L) * temp2;
        HSL_TO_RGB (H, S, L, &wp_r_end, &wp_g_end, &wp_b_end);
    }
    wp_end = (wp_r_end + wp_g_end + wp_b_end) / 3;
    bp_end = (bp_r_end + bp_g_end + bp_b_end) / 3;

/*
printf("\nbp = %f, wp = %f\n", bp, wp);
printf("\nbp_end = %f, wp_end = %f\n", bp_end, wp_end);
printf("\nbp_r = %f, bp_g = %f, bp_b = %f\n", bp_r, bp_g, bp_b);
printf("\nwp_r = %f, wp_g = %f, wp_b = %f\n", wp_r, wp_g, wp_b);
printf("\nbp_r_end = %f, bp_g_end = %f, bp_b_end = %f\n", bp_r_end, bp_g_end, bp_b_end);
printf("\nwp_r_end = %f, wp_g_end = %f, wp_b_end = %f\n", wp_r_end, wp_g_end, wp_b_end);
*/


// ------------------------------------------------------------------------------
// Convert original Histogram using White and Black point values
// ------------------------------------------------------------------------------
// Eredeti hisztogramból a fekete és fehér pont alapján megváltoztatott
// hisztogram létrehozása

// Nem az egész kép újraanalizálása, hanem csak az eredeti hisztogramé,
// mert így csak 256 értéket kell feldolgozni a kép összes pontjai számának
// helyett. Ez a hisztogram az automatikus kontraszt állítás utáni állapotát
// mutatja a képnek

// Ez a hisztogram lesz felhasználva a gamma súlypont megállapításához

    for (i1=0; i1<=255; i1++){
        temp2 = (double)(i1) / 255;

        // bp-től és wp-től viszonyított nullára húzással a kontraszt számolás az alábbi
        //temp2 = bp + ((temp2 - bp) * (1 - bp) / (wp - bp));
        //temp2 = 1 - (1 - temp2) * 1 / (1 - bp);

        // teljes intervallumon számolt húzással a kontraszt számolás az alábbi
        //temp2 = temp2 * wp_end / wp;
        // ---> bp = bp * wp_end / wp;
        // ---> bp_end = bp_end * wp_end / wp;
        //temp2 = 1 - (1 - temp2) * (1 - bp_end * wp_end / wp) / (1 - bp * wp_end / wp);

        // 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
        if ((temp2 > bp_end) && (wp != bp_end)) {
            temp2 = bp_end + (temp2 - bp_end) * (wp_end - bp_end) / (wp - bp_end); }
        // itt a bp fekete pontot is fel kell szorozni a következő számításhoz,
        // mert a bp_end -től viszonyítva nyújtjuk a skálát jobbra a fehér irányába
        // és ezért elmászik a bp
        if (wp != bp_end) {
            temp3 = bp_end + (bp - bp_end) * (wp_end - bp_end) / (wp - bp_end); }
        if ((temp2 < wp_end) && (wp_end != temp3)) {
            temp2 = wp_end - (wp_end - temp2) * (wp_end - bp_end) / (wp_end - temp3); }
        //az 'if' utasításoknál mindenhol vizsgálom hogy ne lehessen nullával való osztás

        if (temp2 > 1){ temp2 = 1; }
        if (temp2 < 0){ temp2 = 0; }
        i2 = (long)(temp2 * 255);
        hist2[i2] = hist2[i2] + hist1[i1];
    }



// ------------------------------------------------------------------------------
// Leave big flat areas of colors out of new histogram
// ------------------------------------------------------------------------------
// Az átlagelõfordulás kétszeresénél többször elõforduló képpontok közül,
// amelyek a hisztogramm két szélének határánál találhatóak,
// ki lesznek hagyva a számításból úgy, hogy egy új hiányos
// hisztogram generálódik a mûvelethez, amelyben nincsenek jelen
// másszóval csak a részletekre kell koncentrálni, a nagy homogén
// felületeket nem akarom számtásba venni
/*
    i2 = 0;
    hist_min = bw * bh;
    hist_max = 0;
    hist_avg = 0;
    // A különbözõ fényerõk átlag elõfordulásának kiszámítása
    for (i1=0; i1<=255; i1++){
        i2 = hist2[i1];
        if (hist_min > i2){ hist_min = i2; }
        if (hist_max < i2){ hist_max = i2; }
        hist_avg = hist_avg + i2;
    }
    hist_avg = hist_avg / 256;
      hist2_occur_count = 0;
    for (i1=0; i1<=255; i1++){
        i2 = hist2[i1];
        if ((i2 >= hist_avg*2) && ((i1 < occur_edge * 255) || (i1 > (1 - occur_edge) * 255))){
            hist4[i1] = 0;
            // a számításból kihagyandó "kiugró" színek pozíciójának letárolása
            hist2_occur[hist2_occur_count] = i1;
            hist2_occur_count += 1;
        }
        else{
            hist4[i1] = i2;
        }
    }
    // Csak akkor számolunk a hiányos tömbbel, ha egy megadott maximum
    // értéknél azért nem több "nagyban elõforduló szín" van jelen,
    // Ez jelenleg maximumra állítva, tehát nem szabályozom a maximális számukat
    i2 = 0;
    if (hist2_occur_count <= occur_max) {
        for (i1=0; i1<=255; i1++){ hist2[i1] = hist4[i1]; i2 += hist2[i1]; }
    }
*/

// ------------------------------------------------------------------------------
// Gamma value calculating
// ------------------------------------------------------------------------------
// Gamma súlypont megállapítása a második hisztogram alapján, ami már az
// állított kontraszt utáni helyzetet mutatja
// A végeredmény azt adja meg, hogy mennyire kell világosítani, vagy éppen
// sötétíteni a képet, hogy az össz fényereje a képnek egyensúlyban legyen

// A gamma súlypont az az érték, amely a hisztogramban azt mutatja,
// hogy tõle balra és jobbra egyaránt egyforma számú képpont található
// (vagyis fele a kép összes pontjainak)

// Ezt úgy kapjuk meg, hogy elkezdjük olvasni a hisztogram értékeit az
// egyik oldalról befelé, és közben össze adjuk a kapott értékeket
// Ha ez az érték elérte vagy túllépte a kép összes pontjainak a számának
// felét, akkor megállunk és a tömb aktuális indexe adja meg
// a gamma súlypont megfelelõ értékét

/*
    gamma_weight_mid_all = 0;
    for (i1=0;   i1<=255; i1++){ gamma_weight_mid_all  += hist2[i1]; }
    i3 = 0;
    flag1 = 0;
    gamma_weight_mid = 0;
    for (i1=0; i1<=255; i1++){
        i3 = i3 + hist2[i1];
        if (flag1 == 0){
            if (i3 > gamma_weight_mid_all / 2){
                flag1 = 1;
                gamma_weight_mid = i1;
            }
        }
    }
    gamma_weight_mid = gamma_weight_low / 255;
    gamma_mid = 1;
    gamma_mid = log(gamma_interval_mid) / log(gamma_weight_mid);
    if (gamma_mid < (1/gamma_max)){ gamma_mid = (1/gamma_max); }
    if (gamma_mid > gamma_max){ gamma_mid = gamma_max; }

    // Convert CONTRAST Histogram using MID GAMMA VALUE
    for (i1=0; i1<=255; i1++){
        temp2 = i1;
        temp2 = pow(temp2 / 255, gamma_mid) * 255;
        i2 = (long)temp2;
        if (i2 > 255){ i2 = 255; }
        if (i2 < 0){ i2 = 0; }
        hist2b[i2] = hist2b[i2] + hist2[i1];
    }
*/

    // Hisztogramm súlyának megállapítása
    gamma_weight_low_all = 0;
    gamma_weight_high_all = 0;
    for (i1=0;   i1<=127; i1++){ gamma_weight_low_all  += hist2[i1]; }
    for (i1=128; i1<=255; i1++){ gamma_weight_high_all += hist2[i1]; }

    // Hisztogramm súlypont megállapítása
    i3 = 0;
    flag1 = 0;
    gamma_weight_low = 0;
    for (i1=0; i1<=127; i1++){
        i3 = i3 + hist2[i1];
        if (flag1 == 0){
            if (i3 > gamma_weight_low_all / 2){
                flag1 = 1;
                gamma_weight_low = i1;
            }
        }
    }
    i3 = 0;
    flag1 = 0;
    gamma_weight_high = 0;
    for (i1=128; i1<=255; i1++){
        i3 = i3 + hist2[i1];
        if (flag1 == 0){
            if (i3 > gamma_weight_high_all / 2){
                flag1 = 1;
                gamma_weight_high = i1;
            }
        }
    }
    gamma_weight_low = gamma_weight_low / 255;
    gamma_weight_high = gamma_weight_high / 255;

    // Súlypont eltolás szükségességének megállapítása
    gamma_low = 1;
    gamma_high = 1;

    // gammát csak egyírányban toljuk el,
    // vagyis csak világosítunk ha szükséges, de soha sem sötétítünk
    if (gamma_weight_low < gamma_interval_low){
        gamma_low = log(gamma_interval_low) / log(gamma_weight_low);
    }
    if (gamma_weight_high > gamma_interval_high){
        gamma_high = log(gamma_interval_high) / log(gamma_weight_high);
    }

    if (gamma_low < (1/gamma_max)){ gamma_low = (1/gamma_max); }
    if (gamma_low > gamma_max){ gamma_low = gamma_max; }
    if (gamma_high < (1/gamma_max)){ gamma_high = (1/gamma_max); }
    if (gamma_high > gamma_max){ gamma_high = gamma_max; }



// ------------------------------------------------------------------------------
// Recalculate the RGB values by setting the CONTRAST, COLOR BALANCE and GAMMA
// ------------------------------------------------------------------------------
// Kép színeinek újrakalkulálása (kontraszt, színegyensúly és gamma korrekció)
// A kép összes pontja újrakalkulálódik és visszaíródik a pufferba

// A gamma állításnál a kép színének RGB-jét a gammához mérten nem külön
// színcsatornánként, hanem a fényerejükhöz mérten egyben vannnak állítva
// A gamma úgy állítódik, hogy a súlypont el van tolva 128-ba
// (tehát ha kisebb az értéke akkor növekszik, ha nagyobb, akkor meg csökken)
// és ez magával húzza nyújtásos módon arányosan a közép színeket
// a 128 irányába

    for (y=0; y<=bh-1; y++){
        addr2 = y * bw * 3 + y * addr_offset;
        for (x=0; x<=bw-1; x++){
            addr = addr2 + x * 3;

            // apply changes ONLY on selected area of the image
            if ((apply_on_selection == 0) || ((apply_on_selection != 0) &&
                (x >= x1 &&
                x <= x2 &&
                y >= y1 &&
                y <= y2))) {

            col_r2 = image_buffer[addr + 0];
            col_g2 = image_buffer[addr + 1];
            col_b2 = image_buffer[addr + 2];

            col_r2 = col_r2 / 255;
            col_g2 = col_g2 / 255;
            col_b2 = col_b2 / 255;


            // CONTRAST SHIFT AND COLOR BALANCE
            // 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
            if ((col_r2 > bp_r_end) && (wp_r != bp_r_end)) {
                col_r2 = bp_r_end + (col_r2 - bp_r_end) * (wp_r_end - bp_r_end) / (wp_r - bp_r_end); }
            if ((col_g2 > bp_g_end) && (wp_g != bp_g_end)) {
                col_g2 = bp_g_end + (col_g2 - bp_g_end) * (wp_g_end - bp_g_end) / (wp_g - bp_g_end); }
            if ((col_b2 > bp_b_end) && (wp_b != bp_b_end)) {
                col_b2 = bp_b_end + (col_b2 - bp_b_end) * (wp_b_end - bp_b_end) / (wp_b - bp_b_end); }

            // itt a bp fekete pontot is fel kell szorozni a következő számításhoz,
            // mert a bp_end -től viszonyítva nyújtjuk a skálát jobbra a fehér irányába
            // és ezért elmászik a bp
            if (wp_r != bp_r_end) {
                temp3 = bp_r_end + (bp_r - bp_r_end) * (wp_r_end - bp_r_end) / (wp_r - bp_r_end); }
            if ((col_r2 < wp_r_end) && (wp_r_end != temp3)) {
                col_r2 = wp_r_end - (wp_r_end - col_r2) * (wp_r_end - bp_r_end) / (wp_r_end - temp3); }

            if (wp_g != bp_g_end) {
                temp3 = bp_g_end + (bp_g - bp_g_end) * (wp_g_end - bp_g_end) / (wp_g - bp_g_end); }
            if ((col_g2 < wp_g_end) && (wp_g_end != temp3)) {
                col_g2 = wp_g_end - (wp_g_end - col_g2) * (wp_g_end - bp_g_end) / (wp_g_end - temp3); }

            if (wp_b != bp_b_end) {
                temp3 = bp_b_end + (bp_b - bp_b_end) * (wp_b_end - bp_b_end) / (wp_b - bp_b_end); }
            if ((col_b2 < wp_b_end) && (wp_b_end != temp3)) {
                col_b2 = wp_b_end - (wp_b_end - col_b2) * (wp_b_end - bp_b_end) / (wp_b_end - temp3); }

            // határérték ellenőrzés és visszaírás
            if (col_r2 > 1){ col_r2 = 1; }
            if (col_g2 > 1){ col_g2 = 1; }
            if (col_b2 > 1){ col_b2 = 1; }
            if (col_r2 < 0){ col_r2 = 0; }
            if (col_g2 < 0){ col_g2 = 0; }
            if (col_b2 < 0){ col_b2 = 0; }


            // GAMMA CORRECTION
            // megjegyzés: ez a gamma felhúzásos módszer színesebb végeredményt ad
            // mint amelyiknél külön - külön toljuk a színeket arányosan
            temp2 = (col_r2 + col_g2 + col_b2) / 3;
            cc = (long)(temp2 * 255);

            //temp2 = pow(temp2 / 255, gamma_mid) * 255;
            if (temp2 <= 0.5){ temp3 = pow(temp2 * 2, gamma_low) / 2; }
            else{ temp3 = pow((temp2 - 0.5) * 2, gamma_high) / 2 + 0.5; }

            //temp3 = pow(temp2 / 255, gamma_exp) * 255;
            if (temp2 < temp3){
                if (temp2 < 1){
                    if (temp2 > 0){
                        col_r2 = ((1 - (1 - col_r2) * (1 - temp3)
                            / (1 - temp2)) + (col_r2 * temp3 / temp2)) / 2;
                        col_g2 = ((1 - (1 - col_g2) * (1 - temp3)
                            / (1 - temp2)) + (col_g2 * temp3 / temp2)) / 2;
                        col_b2 = ((1 - (1 - col_b2) * (1 - temp3)
                            / (1 - temp2)) + (col_b2 * temp3 / temp2)) / 2;
                    }
                }
            }
            else{
                if (temp2 > 0){
                    col_r2 = col_r2 * temp3 / temp2;
                    col_g2 = col_g2 * temp3 / temp2;
                    col_b2 = col_b2 * temp3 / temp2;
                }
            }

            // határérték ellenőrzés és visszaírás
            if (col_r2 > 1){ col_r2 = 1; }
            if (col_g2 > 1){ col_g2 = 1; }
            if (col_b2 > 1){ col_b2 = 1; }
            if (col_r2 < 0){ col_r2 = 0; }
            if (col_g2 < 0){ col_g2 = 0; }
            if (col_b2 < 0){ col_b2 = 0; }


            col_r = (long)(col_r2 * 255);
            col_g = (long)(col_g2 * 255);
            col_b = (long)(col_b2 * 255);
            image_buffer[addr + 0] = col_r & 0xff;
            image_buffer[addr + 1] = col_g & 0xff;
            image_buffer[addr + 2] = col_b & 0xff;

            // Build up Histogram for SATURATION
            if (x >= x1 &&
                x <= x2 &&
                y >= y1 &&
                y <= y2) {
                    double H, S, L;
                    RGB_TO_HSL (col_r2, col_g2, col_b2, &H, &S, &L);
                    // Az 'S' értékét a szürke egyenes közepétől távolodva kisebbnek veszem itt,
                    // mert az optikailag egyre kevésbé tűnik színesnek,
                    // és ennél a résznél optikailag vizsgálok
                    if (L > 0.5) { L = 1 - L; }
                    S = S * L * 2;
                    // Ha S = 0, vagyis szürke a szín, akkor nem adom hozzá
                    // a színtelítettség hisztogramjához értelemszerűen
                    if (S > 0) {
                        cc = (long)(S * 255);
                        hist_satur[cc]++;
                    }
            }

            }
        }
    }



// ------------------------------------------------------------------------------
// Recalculate the RGB values by setting the SATURAION
// ------------------------------------------------------------------------------

    // Hisztogram átlag értékének megállapítása
    hist_satur_avg = 0;
    for (i1=255; i1>=0; i1--){
        hist_satur_avg += hist_satur[i1];
    }
    hist_satur_avg = hist_satur_avg / 255;
    temp1 = hist_satur_avg * 0.1;

    // Hisztogram szélének keresése a színek felhúzásához
    i3 = 0;
    flag1 = 0;
    for (i1=255; i1>=0; i1--){
        if (flag1 == 0){
            if (hist_satur[i1] >= temp1){
                flag1 = 1;
                i3 = i1;
            }
        }
    }
    hist_satur_low = (double)(i3) / 255;

    // Határérték ellenőrzés
    if (hist_satur_low > satur_max){ hist_satur_low = satur_max; }
    hist_satur_ok = 0;
    if (hist_satur_low > 0){ hist_satur_ok = satur_max / hist_satur_low; }

    for (y=0; y<=bh-1; y++){
        addr2 = y * bw * 3 + y * addr_offset;
        for (x=0; x<=bw-1; x++){
            addr = addr2 + x * 3;

            // apply changes ONLY on selected area of the image
            if ((apply_on_selection == 0) || ((apply_on_selection != 0) &&
                (x >= x1 &&
                x <= x2 &&
                y >= y1 &&
                y <= y2))) {

            col_r2 = image_buffer[addr + 0];
            col_g2 = image_buffer[addr + 1];
            col_b2 = image_buffer[addr + 2];

            col_r2 = col_r2 / 255;
            col_g2 = col_g2 / 255;
            col_b2 = col_b2 / 255;

            RGB_TO_HSL (col_r2, col_g2, col_b2, &H, &S, &L);

            // szín telítettségének felszorzása a maxmimum megengedettig
            double S_new;
            S_new = S * hist_satur_ok;
            if (S_new <= satur_max) { S = S_new; }

            HSL_TO_RGB (H, S, L, &col_r2, &col_g2, &col_b2);

            col_r = (long)(col_r2 * 255);
            col_g = (long)(col_g2 * 255);
            col_b = (long)(col_b2 * 255);
            image_buffer[addr + 0] = col_r & 0xff;
            image_buffer[addr + 1] = col_g & 0xff;
            image_buffer[addr + 2] = col_b & 0xff;

            //Mellékesen a legvégső Hisztogram létrehozása is
            cc = (long)((double)(col_r + col_g + col_b) / 3);
            hist3[cc]++;

            }
        }
    }



// a test rész csak akkor működik, ha van math library, mert itt használok szögfüggvényeket

// ------------------------------------------------------------------------------
// TEST: Show Histograms by Drawing them on Image
// ------------------------------------------------------------------------------
//
    // csak normál RGB tömbnél élhet a tesztelés
    if ((format_flag == 0) && (test_flag == 1)) {
        // a max érték kezdõértése 1, hogy 0-val való osztás ne fordulhasson elõ
        long hist1_max = 1;
        long hist2_max = 1;
        long hist3_max = 1;
        long histS_max = 1;

        // Figyelem! Többszöri lefuttatása a rutinnak ugyanazon a képen
        // nem várt eredményt produkál ha a hisztogrammok is ki vannak rajzolva,
        // mert akkor már a teszt képet is beleveszi a számításba
        for (i1=0; i1<=255; i1++){ if (hist1_max < hist1[i1]) { hist1_max = hist1[i1]; } }
        for (i1=0; i1<=255; i1++){ if (hist2_max < hist2[i1]) { hist2_max = hist2[i1]; } }
        for (i1=0; i1<=255; i1++){ if (hist3_max < hist3[i1]) { hist3_max = hist3[i1]; } }
        for (i1=0; i1<=255; i1++){ if (histS_max < hist_satur[i1]) { histS_max = hist_satur[i1]; } }

        for (y=0; y<=bh-1; y++){
            addr2 = y * bw * 3 + y * addr_offset;
            for (x=0; x<=bw-1; x++){
                addr = addr2 + x * 3;
                xm = x;
                ym = y;
                if (format_flag == 1) { ym = bh - 1 - ym; }
                if (format_flag == 2) { ym = bh - 1 - ym; }

                // Keret rajzolása a hisztogrammok köré 1 pixel szélességben
                if (((xm == 256) && (ym <= 400)) || ((ym == 400) && (xm <= 256))) {
                        col = color_black;
                        image_buffer[addr + 2] = (col >> 0)  & 0xff;
                        image_buffer[addr + 1] = (col >> 8)  & 0xff;
                        image_buffer[addr + 0] = (col >> 16) & 0xff;
                }

                // Hisztogrammok kirajzolása
                if ((xm >= 0) && (xm <= 255)) {

                    // 1. hisztogramm: EREDETI KÉP ÁLLAPOTA
                    if (ym <= 99) {
                        i2 = hist1[xm] * 99 / hist1_max;
                        if (99 - ym >= i2) {
                            if ((xm <= (long)(bp_end * 255)) || (xm >= (long)(wp_end * 255))) {
                                col = color_green_dark;
                            }
                            else {
                                col = color_black;
                            }
                        }
                        else {
                            col = color_green;
                        }
                        if (xm == (long)(bp * 255)) { col = color_yellow; }
                        if (xm == (long)(wp * 255)) { col = color_yellow; }
                        image_buffer[addr + 2] = (col >> 0)  & 0xff;
                        image_buffer[addr + 1] = (col >> 8)  & 0xff;
                        image_buffer[addr + 0] = (col >> 16) & 0xff;
                    }

                    // 2. hisztogramm: KONTRASZT UTÁN
                    if ((ym >= 100) && (ym <= 199)) {
                        i2 = hist2[xm] * 99 / hist2_max;
                        if (199 - ym >= i2) {
                            if ((xm <= (long)(gamma_interval_low * 255))
                                || (xm >= (long)(gamma_interval_high * 255)))
                            {
                                col = color_brown;
                            }
                            else{
                                col = color_black;
                            }
                        }
                        else {
                            col = color_green;
                        }
                        // Gamma alsó súlypont
                        if (xm == (long)(gamma_weight_low * 255)) {
                            col = color_yellow;
                        }
                        // Gamma felső súlypont
                        if (xm == (long)(gamma_weight_high * 255)) {
                            col = color_yellow;
                        }
                        image_buffer[addr + 2] = (col >> 0)  & 0xff;
                        image_buffer[addr + 1] = (col >> 8)  & 0xff;
                        image_buffer[addr + 0] = (col >> 16) & 0xff;
                    }

                    // 3. hisztogramm SATURATION
                    if ((ym >= 200) && (ym <= 299)) {
                        i2 = hist_satur[xm] * 99 / histS_max;
                        if (299 - ym >= i2) {
                            if (xm >= (long)(satur_max * 255))
                            {
                                col = color_brown;
                            }
                            else{
                                col = color_black;
                            }
                        }
                        else {
                            col = color_blue;
                        }
                        //if (xm == (long)((satur_max)* 255)) { col = color_red; }
                        if (xm == (long)((hist_satur_low)* 255)) { col = color_yellow; }
                        image_buffer[addr + 2] = (col >> 0)  & 0xff;
                        image_buffer[addr + 1] = (col >> 8)  & 0xff;
                        image_buffer[addr + 0] = (col >> 16) & 0xff;
                    }

                    // 4. hisztogramm: KONTRASZT, GAMMA és SATURATION UTÁN (VÉGSŐ)
                    if ((ym >= 300) && (ym <= 399)) {
                        i2 = hist3[xm] * 99 / hist3_max;
                        if (399 - ym >= i2) {
                            col = color_black;
                        }
                        else {
                            col = color_green;
                        }
                        image_buffer[addr + 2] = (col >> 0)  & 0xff;
                        image_buffer[addr + 1] = (col >> 8)  & 0xff;
                        image_buffer[addr + 0] = (col >> 16) & 0xff;
                    }

                    // 5. Fekete és fehér pont színirányának kirajzolása egy körbe
                    // konstans a kör sugarához
                    const double rad = 100;
                    // konstans a körvonal vastagságához
                    const double outline = 5;
                    // pi értéke
                    const double pi = 3.1415926535897932;
                    if ((ym >= 400) && (ym <= 400+rad*2)) {
                        double rr, rx, ry;

                        rx = xm - rad;
                        ry = ym - 400 - rad;
                        rr = sqrt(rx*rx + ry*ry);

                        // KÖRÍV MEGRAJZOLÁSA
                        if ((rr <= rad) && (rr >= rad-outline)) {
                                H = 0;
                                if ((rx >= 0) && (ry <  0)) { H = asin( rx / rr) / pi / 2 + 0.00; }
                                if ((rx >= 0) && (ry >= 0)) { H = asin( ry / rr) / pi / 2 + 0.25; }
                                if ((rx <  0) && (ry >= 0)) { H = asin(-rx / rr) / pi / 2 + 0.50; }
                                if ((rx <  0) && (ry <  0)) { H = asin(-ry / rr) / pi / 2 + 0.75; }
                                S = 1;
                                L = 0.5;
                                L = rad - rr;
                                if (L > outline / 2) { L = outline - L; }
                                L = L / outline;
                                HSL_TO_RGB (H, S, L, &col_r2, &col_g2, &col_b2);
                                col_r = (long)(col_r2 * 255);
                                col_g = (long)(col_g2 * 255);
                                col_b = (long)(col_b2 * 255);
                                image_buffer[addr + 0] = col_r & 0xff;
                                image_buffer[addr + 1] = col_g & 0xff;
                                image_buffer[addr + 2] = col_b & 0xff;
                        }
                        else {

                            col = color_black;
                            double px, py, lx, ly, d;
                            px = 0; py = 0;
                            lx = 0; ly = 0;

                            // FEKETE PONT SZÍNIRÁNYA EGYENESÉNEK MEGHÚZÁSA
                            // Szürke pontnál nem jelenik meg egyenes a körben
                            RGB_TO_HSL (bp_r, bp_g, bp_b, &H, &S, &L);
                            //printf("\nH = %f, S = %f, L = %f\n", H, S, L);

                            if ((H >= 0.00) && (H < 0.25)) { lx =  sin((H - 0.00) * 2 * pi) * rr; ly =  cos((H - 0.00) * 2 * pi) * rr; }
                            if ((H >= 0.25) && (H < 0.50)) { lx =  cos((H - 0.25) * 2 * pi) * rr; ly = -sin((H - 0.25) * 2 * pi) * rr; }
                            if ((H >= 0.50) && (H < 0.75)) { lx = -sin((H - 0.50) * 2 * pi) * rr; ly = -cos((H - 0.50) * 2 * pi) * rr; }
                            if ((H >= 0.75) && (H < 1.00)) { lx = -cos((H - 0.75) * 2 * pi) * rr; ly =  sin((H - 0.75) * 2 * pi) * rr; }
                            px = lx * S;
                            py = ly * S;

                            d = ly * rx + lx * ry;
                            d = d / sqrt(lx * lx + ly * ly);
                            if (d < 0) { d = 0 - d; }

                            if ((d < 1) && (rr < rad) && (sgn(rx) == sgn(px)) && (sgn(ry) == -sgn(py))) {
                                if (rr < rad * S) { col = color_red; }
                                else { col = color_green_dark; }
                            }

                            // FEHÉR PONT SZÍNIRÁNYA EGYENESÉNEK MEGHÚZÁSA
                            RGB_TO_HSL (wp_r, wp_g, wp_b, &H, &S, &L);

                            if ((H >= 0.00) && (H < 0.25)) { lx =  sin((H - 0.00) * 2 * pi) * rr; ly =  cos((H - 0.00) * 2 * pi) * rr; }
                            if ((H >= 0.25) && (H < 0.50)) { lx =  cos((H - 0.25) * 2 * pi) * rr; ly = -sin((H - 0.25) * 2 * pi) * rr; }
                            if ((H >= 0.50) && (H < 0.75)) { lx = -sin((H - 0.50) * 2 * pi) * rr; ly = -cos((H - 0.50) * 2 * pi) * rr; }
                            if ((H >= 0.75) && (H < 1.00)) { lx = -cos((H - 0.75) * 2 * pi) * rr; ly =  sin((H - 0.75) * 2 * pi) * rr; }
                            px = lx * S;
                            py = ly * S;

                            d = ly * rx + lx * ry;
                            d = d / sqrt(lx * lx + ly * ly);
                            if (d < 0) { d = 0 - d; }

                            if ((d < 1) && (rr < rad) && (sgn(rx) == sgn(px)) && (sgn(ry) == -sgn(py))) {
                                if (rr < rad * S) { col = color_yellow; }
                                else { col = color_brown; }
                            }

                            image_buffer[addr + 2] = (col >> 0)  & 0xff;
                            image_buffer[addr + 1] = (col >> 8)  & 0xff;
                            image_buffer[addr + 0] = (col >> 16) & 0xff;

                        }
                    }
                }
            }
        }
    }


}



// ------------------------------
// ----- MAIN AARGB ENTRIES -----
// ------------------------------

void AARGB_NORMAL(
    unsigned char *image_buffer,
    int image_width,
    int image_height)
{
    AARGB_MAIN(
        image_buffer,
        image_width,
        image_height,
        0,
        0,
        image_width-1,
        image_height-1,
        0,
        0,
        0);
}

void 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)
{
    AARGB_MAIN(
        image_buffer,
        image_width,
        image_height,
        x1,
        y1,
        x2,
        y2,
        0,
        apply_on_selection,
        0);
}

void AARGB_DIB(
    unsigned char *image_buffer,
    int image_width,
    int image_height)
{
    AARGB_MAIN(
        image_buffer,
        image_width,
        image_height,
        0,
        0,
        image_width-1,
        image_height-1,
        1,
        0,
        0);
}

void 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)
{
    AARGB_MAIN(
        image_buffer,
        image_width,
        image_height,
        x1,
        y1,
        x2,
        y2,
        1,
        apply_on_selection,
        0);
}

void AARGB_BMP(
    unsigned char *image_buffer)
{
      long f_bm;
      long f_bitcount;
      long f_compressed;
      long f_offs;
      long f_width;
      long f_height;

      f_bm = 0;
      f_bm += image_buffer[0] << 0;
      f_bm += image_buffer[1] << 8;

      f_bitcount = 0;
      f_bitcount += image_buffer[28] << 0;
      f_bitcount += image_buffer[29] << 8;

      f_compressed = 0;
      f_compressed += image_buffer[30] << 0;
      f_compressed += image_buffer[31] << 8;
      f_compressed += image_buffer[32] << 16;
      f_compressed += image_buffer[33] << 24;

      if ((f_bm == 0x00004d42) && (f_bitcount == 24) && (f_compressed == 0)) {

            f_offs = 0;
            f_offs += image_buffer[10] << 0;
            f_offs += image_buffer[11] << 8;
            f_offs += image_buffer[12] << 16;
            f_offs += image_buffer[13] << 24;

            f_width = 0;
            f_width += image_buffer[18] << 0;
            f_width += image_buffer[19] << 8;
            f_width += image_buffer[20] << 16;
            f_width += image_buffer[21] << 24;

            f_height = 0;
            f_height += image_buffer[22] << 0;
            f_height += image_buffer[23] << 8;
            f_height += image_buffer[24] << 16;
            f_height += image_buffer[25] << 24;

            AARGB_MAIN(
                  image_buffer + f_offs,
                  f_width,
                  f_height,
                  0,
                  0,
                  f_width-1,
                  f_height-1,
                        2,
                  0,
                        0);
      }
}

void AARGB_BMP_SEL(
    unsigned char *image_buffer,
    int x1,
    int y1,
    int x2,
    int y2,
    int apply_on_selection)
{
      long f_bm;
      long f_bitcount;
      long f_compressed;
      long f_offs;
      long f_width;
      long f_height;

      f_bm = 0;
      f_bm += image_buffer[0] << 0;
      f_bm += image_buffer[1] << 8;

      f_bitcount = 0;
      f_bitcount += image_buffer[28] << 0;
      f_bitcount += image_buffer[29] << 8;

      f_compressed = 0;
      f_compressed += image_buffer[30] << 0;
      f_compressed += image_buffer[31] << 8;
      f_compressed += image_buffer[32] << 16;
      f_compressed += image_buffer[33] << 24;

      if ((f_bm == 0x00004d42) && (f_bitcount == 24) && (f_compressed == 0)) {

            f_offs = 0;
            f_offs += image_buffer[10] << 0;
            f_offs += image_buffer[11] << 8;
            f_offs += image_buffer[12] << 16;
            f_offs += image_buffer[13] << 24;

            f_width = 0;
            f_width += image_buffer[18] << 0;
            f_width += image_buffer[19] << 8;
            f_width += image_buffer[20] << 16;
            f_width += image_buffer[21] << 24;

            f_height = 0;
            f_height += image_buffer[22] << 0;
            f_height += image_buffer[23] << 8;
            f_height += image_buffer[24] << 16;
            f_height += image_buffer[25] << 24;

            AARGB_MAIN(
                  image_buffer + f_offs,
                  f_width,
                  f_height,
                  x1,
                  y1,
                  x2,
                  y2,
                        2,
                  apply_on_selection,
                        0);
      }
}












// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// ---- HERE I PUT MY OUTDATED CODE THAT I PROBABLY WON'T USE ANYMORE ----
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------



/*
// Fõ belépési pont a DLL-be, jelenleg nem szükséges
int WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            // attach to process
            // return 1 to fail DLL load
            break;

        case DLL_PROCESS_DETACH:
            // detach from process
            break;

        case DLL_THREAD_ATTACH:
            // attach to thread
            break;

        case DLL_THREAD_DETACH:
            // detach from thread
            break;
    }
    return 0; // succesful
}
*/

/*
// Elõzõ beállítás az átlag RGB értékekhez
    wp_r = col_r3[wp];
    wp_g = col_g3[wp];
    wp_b = col_b3[wp];
    bp_r = col_r3[bp];
    bp_g = col_g3[bp];
    bp_b = col_b3[bp];
    i2 = hist1[wp];
    i3 = hist1[bp];
    if (i2 > 0){
        wp_r = wp_r / i2;
        wp_g = wp_g / i2;
        wp_b = wp_b / i2;
    }
    if (i3 > 0){
        bp_r = bp_r / i3;
        bp_g = bp_g / i3;
        bp_b = bp_b / i3;
    }
*/

/*
// Gamma value calculating
// Elõzõ gamma állítási rutin

    i3 = 0;
    i2 = bw * bh / 2;
    gamma_s = 0;
    flag1 = 0;
    for (i1=0; i1<=255; i1++){
        i3 = i3 + hist2[i1];
        if (flag1 == 0){
            if (i3 > i2){
                flag1 = 1;
                gamma_s = i1;
            }
        }
    }
    if (gamma_s <= 0){ gamma_s = 1; }
    if (gamma_s >= 255){ gamma_s = 254; }
    if (abs(gamma_s - 128) > (128 * gamma_max)){
       if (gamma_s < 128){
           gamma_s = 128 - 128 * gamma_max;
       }
       else{
           gamma_s = 128 + 128 * gamma_max;
       }
    }
*/

/*
// Gamma value calculating
// 2-es verzió gamma állítási rutin

            if (gamma_s < 128){
              if (gamma_s > cc){
                  temp3 = temp2 + (255 - (255 - temp2)
                   * (128 / (255 - gamma_s)) - temp2) * (temp2 / gamma_s);
              }
              else{
                  temp3 = 255 - (255 - temp2) * 128 / (255 - gamma_s);
              }
            }
            else{
              if (gamma_s > cc){
                  temp3 = temp2 * 128 / gamma_s;
              }
              else{
                  temp3 = temp2 - (temp2 - temp2 * (128 / gamma_s))
                   * ((255 - temp2) / (255 - gamma_s));
              }
            }
*/

/*
// Gamma value calculating
// 3-as verzió gamma állítási rutin

                  col_r2 = pow(col_r2 / 255, gamma_exp) * 255;
                  col_g2 = pow(col_g2 / 255, gamma_exp) * 255;
                  col_b2 = pow(col_b2 / 255, gamma_exp) * 255;
*/





/*
    hist_min = bw * bh;
    hist_max = 0;
    hist_avg = 0;

// Hisztogram átlagának megállapítása külön - külön a bal és jobb oldalra
// az alulexponálás kiküszöbölésére
    hist_low_point = 0;
    hist_high_point = 255;
    flag1 = 0;
    for (i1=0; i1<=255; i1++){
        if (flag1 == 0){
            if (hist1[i1] == 0){
                hist_low_point = i1;
            }
            else{
                flag1 = 1;
            }
        }
    }
    flag1 = 0;
    for (i1=255; i1>=0; i1--){
        if (flag1 == 0){
            if (hist1[i1] == 0){
                hist_high_point = i1;
            }
            else{
                flag1 = 1;
            }
        }
    }

    if (hist_low_point > hist_high_point){
        i1 = hist_high_point;
        hist_high_point = hist_low_point;
        hist_low_point = i1;
    }
    if (hist_low_point == hist_high_point){
       hist_low_point = hist_low_point - 1;
       hist_high_point = hist_high_point + 1;
    }
    if (hist_low_point < 0){ hist_low_point = 0; }
    if (hist_high_point > 255){ hist_high_point = 255; }
    hist_mid_point = (hist_high_point + hist_low_point) / 2;

    // Átlag fényerõ kiszámítása
    // A maximum és minimum érték számítása csak tesztelési céllal él,
    // nem számít kirtikus idõtényezõnek

    for (i1=0; i1<=255; i1++){
        temp1 = hist1[i1];
        if (hist_min > (long)temp1){ hist_min = (long)temp1; }
        if (hist_max < (long)temp1){ hist_max = (long)temp1; }
        hist_avg = hist_avg + temp1;
    }
    hist_avg = hist_avg / 256;

    hist_avg_low = 0;
    hist_avg_high = 0;
    counter = 0;
    for (i1=0; i1<=hist_mid_point; i1++){
        hist_avg_low = hist_avg_low + hist1[i1];
        counter++;
    }
    hist_avg_low = hist_avg_low / counter;
    counter = 0;
    for (i1=255; i1>=hist_mid_point; i1--){
        hist_avg_high = hist_avg_high + hist1[i1];
        counter++;
    }
    hist_avg_high = hist_avg_high / counter;


    hist_min_test = hist_min;
    hist_max_test = hist_max;
    hist_avg_test = hist_avg;

    bp = 255;
    //temp1 = cont_max * hist_avg;
    temp1 = cont_max * hist_avg_low;
    flag1 = 0;
    for (i1=0; i1<=hist_mid_point; i1++){
        if (flag1 == 0){
            if (hist1[i1] >= temp1){
                flag1 = 1;
                bp = i1;
            }
        }
    }
    wp = 0;
    temp1 = cont_max * hist_avg_high;
    flag1 = 0;
    for (i1=255; i1>=hist_mid_point; i1--){
        if (flag1 == 0){
            if (hist1[i1] >= temp1){
                flag1 = 1;
                wp = i1;
            }
        }
    }
    // Határértékek beállítása illetve korrekciója
    if (bp > wp){
        i1 = wp;
        wp = bp;
        bp = i1;
    }
    if (bp == wp){
       bp = bp - 1;
       wp = wp + 1;
    }
    if (bp < 0){ bp = 0; }
    if (bp >= 255){ bp = 254; }
    if (wp > 255){ wp = 255; }
    if (wp <= 0){ wp = 1; }
*/




/*
// Gamma value calculating

// Gamma súlypont megállapítása a második hisztogram alapján, ami már az
// állított kontraszt utáni helyzetet mutatja
// A végeredmény azt adja meg, hogy mennyire kell világosítani, vagy éppen
// sötétíteni a képet, hogy az össz fényereje a képnek egyensúlyban legyen

// A gamma súlypont az az érték, amely a hisztogramban azt mutatja,
// hogy tõle balra és jobbra egyaránt egyforma számú képpont található
// (vagyis fele a kép összes pontjainak)

// Ezt úgy kapjuk meg, hogy elkezdjük olvasni a hisztogram értékeit az
// egyik oldalról befelé, és közben össze adjuk a kapott értékeket
// Ha ez az érték elérte vagy túllépte a kép összes pontjainak a számának
// felét, akkor megállunk és a tömb aktuális indexe adja meg
// a gamma súlypont megfelelõ értékét

    i2 = 0;
    hist_min = bw * bh;
    hist_max = 0;
    hist_avg = 0;
    // A különbözõ fényerõk átlag elõfordulásának kiszámítása
    for (i1=0; i1<=255; i1++){
        i2 = hist2[i1];
        if (hist_min > i2){ hist_min = i2; }
        if (hist_max < i2){ hist_max = i2; }
        hist_avg = hist_avg + i2;
    }
    hist_avg = hist_avg / 256;
      hist2_occur_count = 0;
    for (i1=0; i1<=255; i1++){
        i2 = hist2[i1];
        // Az átlagelõfordulás kétszeresénél többször elõforduló képpontok közül,
        // amelyek a hisztogramm két szélének határánál találhatóak,
        // ki lesznek hagyva a számításból úgy, hogy egy új hiányos
        // hisztogram generálódik a mûvelethez, amelyben nincsenek jelen
        // másszóval csak a részletekre kell koncentrálni, a nagy homogán
        // felületeket nem akarom számtásba venni
        if ((i2 >= hist_avg*2) && ((i1 < occur_edge * 255) || (i1 > (1 - occur_edge) * 255))){
            hist4[i1] = 0;
            // a számításból kihagyandó "kiugró" színek pozíciójának letárolása
            hist2_occur[hist2_occur_count] = i1;
            hist2_occur_count += 1;
        }
        else{
            hist4[i1] = i2;
        }
    }
    // Csak akkor számolunk a hiányos tömbbel, ha egy megadott maximum
    // értéknél azért nem több "nagyban elõforduló szín" van jelen,
    // Ez jelenleg maximumra állítva, tehát nem szabályozom a maximális számukat
    i2 = 0;
    if (hist2_occur_count <= occur_max) {
        for (i1=0; i1<=255; i1++){ i2 += hist4[i1]; }
    }
    else {
        for (i1=0; i1<=255; i1++){ i2 += hist2[i1]; }
    }
    // Hisztogramm súlypont megállapítása
    i3 = 0;
    flag1 = 0;
    gamma_s = 0;
    for (i1=0; i1<=255; i1++){
      if (hist2_occur_count <= occur_max) {
            i3 = i3 + hist4[i1];
      }
      else {
            i3 = i3 + hist2[i1];
      }
        if (flag1 == 0){
            if (i3 > i2 / 2){
                flag1 = 1;
                gamma_s = i1;
            }
        }
    }
    gamma_s = gamma_s / 255;
    gamma_s_orig = gamma_s;
    // Súlypont határérték beállítások és korrekciók
    if (gamma_s < gamma_s_min_lo){ gamma_s = gamma_s_min_lo; }
    if (gamma_s > gamma_s_min_hi){ gamma_s = gamma_s_min_hi; }
    if (gamma_s >= gamma_s_max_lo && gamma_s <= gamma_s_max_hi) {
        gamma_exp = 1;
    }
    else
    {
        if (gamma_s < gamma_s_max_lo) {
            gamma_exp = log(gamma_s_max_lo) / log(gamma_s);
        }
        else {
            gamma_exp = log(gamma_s_max_hi) / log(gamma_s);
        }
    }
*/


/*
            cc = (long)((double)(col_r2 + col_g2 + col_b2) / 3);
            temp2 = cc;
            if ((cc > 0) && (cc < 255)){
                if (col_r2 > cc){
                    col_r4 = (col_r2 - cc) / (255 - cc);
                }
                else{
                    col_r4 = (cc - col_r2) / (cc);
                }
                if (col_g2 > cc){
                    col_g4 = (col_g2 - cc) / (255 - cc);
                }
                else{
                    col_g4 = (cc - col_g2) / (cc);
                }
                if (col_b2 > cc){
                    col_b4 = (col_b2 - cc) / (255 - cc);
                }
                else{
                    col_b4 = (cc - col_b2) / (cc);
                }

                temp3 = col_r4;
                if (col_g4 < temp3) temp3 = col_g4;
                if (col_b4 < temp3) temp3 = col_b4;
            }
            else{
                temp3 = 0;
            }
            temp3 = temp3 * 255;
            if(temp3 < 0) temp3 = 0;
            if(temp3 > 255) temp3 = 255;
            cc = (long)(temp3);
            hist_satur[cc]++;
*/




/*
------- TESTING RGB-HSL ---------
    double H, S, L, R, G, B, R2, G2, B2, R3, G3, B3;
    int it;

    long res_ok = 0;
    long res_bad = 0;
    R3 = 0; G3 = 0; B3 = 0;

    for (it=0; it<256*256*256; it++) {

        R = R3 / 255; G = G3 / 255; B = B3 / 255;

        RGB_TO_HSL (R, G, B, &H, &S, &L);
        HSL_TO_RGB (H, S, L, &R2, &G2, &B2);

        R = (double)((int)(R * 100000))/100000;
        G = (double)((int)(G * 100000))/100000;
        B = (double)((int)(B * 100000))/100000;
        R2 = (double)((int)(R2 * 100000))/100000;
        G2 = (double)((int)(G2 * 100000))/100000;
        B2 = (double)((int)(B2 * 100000))/100000;

        double diff;
        diff = abs(R-R2);
        if (diff < abs(G-G2)) { diff = abs(G-G2); }
        if (diff < abs(R-R2)) { diff = abs(R-R2); }

        //if ((R != R2) || (G != G2) || (B != B2)) {
        if (diff > 0.00001) {
            printf ("H = %f\nS = %f\nL = %f\n", H, S, L);
            printf ("R = %f / R2 = %f\nG = %f / G2 = %f\nB = %f / B2 = %f\n", R, R2, G, G2, B, B2);
            printf ("-----------------------------\n");
            res_bad++;
        }
        else { res_ok++; }

        R3++; if (R3 > 255) { R3 = 0; G3++; } if (G3 > 255) { G3 = 0; B3++; printf("%d\n", (int)(B3)); }
    }
    printf ("Result: Ok = %d, Bad = %d\n\n", (int)(res_ok), (int)(res_bad));
    exit(0);
-------- TESTING RGB-HSL -----------
*/



/*
//  Előző rutin a fekete és fehér pont színiránya szög-különbségének megállaptására
    bp_col_dir = 0;
    wp_col_dir = 0;
    bp_col_dist = 0;
    wp_col_dist = 0;
//    cos_30 and pi constans already defined in the beginning part for C compatibility
//    double cos_30 = sqrt((double)(3)/(double)(4)); //0.866025404;
//    double pi = acos(-1); //3.141592654;

    bp_r2 = bp_r / (double)(255);
    bp_g2 = bp_g / (double)(255);
    bp_b2 = bp_b / (double)(255);
    wp_r2 = wp_r / (double)(255);
    wp_g2 = wp_g / (double)(255);
    wp_b2 = wp_b / (double)(255);

    // fekete pont RGB átlagának színeltolása és iránya
    xc = 0 + cos_30 * bp_g2 - cos_30 * bp_b2;
    yc = bp_g2 / 2 + bp_b2 / 2 - bp_r2;

    bp_col_dist = sqrt(xc * xc + yc * yc);
    if (bp_col_dist > 0){
        bp_col_dir = asin(xc / bp_col_dist);
    }

    // fehér pont RGB átlagának színeltolása és iránya
    xc = 0 + cos_30 * wp_g2 - cos_30 * wp_b2;
    yc = wp_g2 / 2 + wp_b2 / 2 - wp_r2;

    wp_col_dist = sqrt(xc * xc + yc * yc);
    if (wp_col_dist > 0){
        wp_col_dir = asin(xc / wp_col_dist);
    }

    // fekete és fehér pont RGB átlagának eltolási irány különbsége (0 és 1 között-re leosztva)
    bp_wp_col_diff = 1;
    if ((bp_col_dist > 0) || (wp_col_dist > 0)){
        // a két szög 0-tól 180 fokig terjedhet, ezek különbségét leosszuk 180 fokkal, azaz PI-vel
        bp_wp_col_diff = (bp_col_dir - wp_col_dir) / pi;
        // abszolút értékét vesszük
        if (bp_wp_col_diff < 0) bp_wp_col_diff = 0 - bp_wp_col_diff;
    }
    // az iránykülönbség mértékével csökkentjük az RGB átlag színeinek erősségét a szürkéhez képest
    // vagyis ha nagyobb a különbség fekete és fehér írányvektorok szöge között,
    // akkor kevesebb színegyensúly korrekciót végzünk

    bp_r = (double)(bp) + (bp_r - (double)(bp)) * (1 - bp_wp_col_diff);
    bp_g = (double)(bp) + (bp_g - (double)(bp)) * (1 - bp_wp_col_diff);
    bp_b = (double)(bp) + (bp_b - (double)(bp)) * (1 - bp_wp_col_diff);
    wp_r = (double)(wp) + (wp_r - (double)(wp)) * (1 - bp_wp_col_diff);
    wp_g = (double)(wp) + (wp_g - (double)(wp)) * (1 - bp_wp_col_diff);
    wp_b = (double)(wp) + (wp_b - (double)(wp)) * (1 - bp_wp_col_diff);
*/


/*
// Előző kontraszt állítási megoldás
            // Contrast shift and color balance

            if ((wp_r - bp_r) != 0){
              col_r2 = bp_r + ((1 - bp_r) * (col_r2 - bp_r)
               / (wp_r - bp_r)); }
            if ((wp_g - bp_g) != 0){
              col_g2 = bp_g + ((1 - bp_g) * (col_g2 - bp_g)
               / (wp_g - bp_g)); }
            if ((wp_b - bp_b) != 0){
              col_b2 = bp_b + ((1 - bp_b) * (col_b2 - bp_b)
               / (wp_b - bp_b)); }
            if (bp_r != 1){
              col_r2 = 1 - (1 * (1 - col_r2) / (1 - bp_r)); }
            if (bp_g != 1){
              col_g2 = 1 - (1 * (1 - col_g2) / (1 - bp_g)); }
            if (bp_b != 1){
              col_b2 = 1 - (1 * (1 - col_b2) / (1 - bp_b)); }
*/


/*
        // Teszt konstansok kiiratása a hisztogrammok alá betűvel és számmal
        CHAR_SET_POSITION(0, 402);

        CHAR_PRINT_TEXT("\nINPUT CONSTANTS\n", color_green);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("CONTRAST MAX = ", color_green);
        CHAR_PRINT_FLOAT(cont_max, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("GAMMA MAX    = ", color_green);
        CHAR_PRINT_FLOAT(gamma_max, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("GAMMA INTERVAL LO = ", color_green);
        CHAR_PRINT_FLOAT(gamma_interval_low, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("GAMMA INTERVAL HI = ", color_green);
        CHAR_PRINT_FLOAT(gamma_interval_high, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);


        // Teszt eredmények kiiratása a hisztogrammok alá betűvel és számmal
        CHAR_PRINT_TEXT("\nOUTPUT RESULTS\n", color_green);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("BLACK POINT   = ", color_green);
        CHAR_PRINT_INTEGER(bp, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("WHITE POINT   = ", color_green);
        CHAR_PRINT_INTEGER(wp, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("HISTOGRAM MIN = ", color_green);
        CHAR_PRINT_INTEGER(hist_min_test, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("HISTOGRAM MAX = ", color_green);
        CHAR_PRINT_INTEGER(hist_max_test, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("HISTOGRAM AVG = ", color_green);
        CHAR_PRINT_FLOAT(hist_avg_test, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("BLACK POINT R = ", color_green);
        CHAR_PRINT_FLOAT(bp_r, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("BLACK POINT G = ", color_green);
        CHAR_PRINT_FLOAT(bp_g, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("BLACK POINT B = ", color_green);
        CHAR_PRINT_FLOAT(bp_b, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("WHITE POINT R = ", color_green);
        CHAR_PRINT_FLOAT(wp_r, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("WHITE POINT G = ", color_green);
        CHAR_PRINT_FLOAT(wp_g, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("WHITE POINT B = ", color_green);
        CHAR_PRINT_FLOAT(wp_b, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("BLACK POINT DIST     = ", color_green);
        CHAR_PRINT_FLOAT(bp_col_dist, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("WHITE POINT DIST     = ", color_green);
        CHAR_PRINT_FLOAT(wp_col_dist, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("BLACK POINT DIR      = ", color_green);
        CHAR_PRINT_FLOAT(bp_col_dir, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("WHITE POINT DIR      = ", color_green);
        CHAR_PRINT_FLOAT(wp_col_dir, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("WHITE BLACK DIR DIFF = ", color_green);
        CHAR_PRINT_FLOAT(bp_wp_col_diff, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);
        CHAR_PRINT_TEXT("\n", color_green);


        CHAR_PRINT_TEXT("GAMMA LOW  = ", color_green);
        CHAR_PRINT_FLOAT(gamma_low, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("GAMMA HIGH = ", color_green);
        CHAR_PRINT_FLOAT(gamma_high, color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);

        CHAR_PRINT_TEXT("SATURATION = ", color_green);
        CHAR_PRINT_FLOAT((1 - hist_satur_low / satur_max), color_yellow);
        CHAR_PRINT_TEXT("\n", color_green);
*/



Generated by  Doxygen 1.6.0   Back to index