
function HistogramBW(img,ch){
    var res = [];
    if (typeof ch === 'undefined' && ch === null)
        ch = 0;
    if (typeof img !== 'undefined' && img !== null)
    {
        var i,j,tmp;
        for (i = 0;i < 256;i++)
            res[i] = 0;

        for (i = 0;i < img.length;i++)
        {
            for (j = 0;j < img[i].length;j++)
            {
               tmp = Math.round(img[i][j][ch]);
               if (tmp < 0)
               {
                   res[0]++;
                   continue;
               }
               if (tmp > 255)
               {
                   res[255]++;
                   continue;
               }
               res[tmp]++;
            }
        }
        
    }
    
    return res;
}

function HistogramTable1D(img){
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0)
    {
        var i,tmp;
        for (i = 0;i < img.length;i++)
            res[i] = 0;

        for (i = 0;i < img.length;i++)
        {
            tmp = Math.round(img[i]);
            if (tmp < 0)
            {
               res[0]++;
               continue;
            }
            if (tmp > img.length-1)
            {
               res[img.length-1]++;
               continue;
            }
            res[tmp]++;
        }
        
    }
    
    return res;
}


function NormalizedHistogramBW(img,ch){
    var res = [];
    if (typeof ch === 'undefined' && ch === null)
        ch = 0;
    if (typeof img !== 'undefined' && img !== null)
    {
	var hist = HistogramBW(img,ch);
	if (hist.length > 0)
	{
            var i,sum_ = 0;
            for (i = 0;i < hist.length;i++)
		sum_ = sum_ + hist[i];
            for (i = 0;i < hist.length;i++)
		res[i] = hist[i]/sum_;
	}

    }
    return res;
}

function HistogramNValues(tab,maxValue) {
    var i,j,k, res = [];
    res[0] = [];
    
    for (k = 0;k < maxValue;k++)
    {
    	res[0][k] = 0;
    }
    for (i = 0;i < tab.length;i++)
    {
	for (j = 0;j < tab[i].length;j++)
    	{
	    res[0][tab[i][j]]++;
    	}
    }
    return res;
}


function HistogtramAxisX(){
    var res = [],i;
    for (i = 0;i < 256;i++)
    	res[i] = i;
    
    return res;
}

function Negative(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var i,j,k;
        var n = img[0][0].length;
        if (n > 3)
            n = 3;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
                for (k = 0;k < n;k++)
                    res[i][j][k] = 255-img[i][j][k];
                res[i][j][3] = 255;
            }
        }
        
    }
    return res;
}

function Negative2DTable(tab,v)
{
    var res = [];
    if (v !== 'undefined' && v !== null && typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
        var i,j;
        for (i = 0;i < tab.length;i++)
        {
            res[i] = [];
            for (j = 0;j < tab[i].length;j++)
            {
                res[i][j] = v - tab[i][j];
            }
        }
        
    }
    return res;
}

function GetR2DTable(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var n = img[0][0].length,i,j;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = img[i][j][0];
            }
        }
    }
    return res;
}


function GetG2DTable(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var n = img[0][0].length,i,j;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = img[i][j][1];
            }
        }
    }
    return res;
}

function GetB2DTable(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var n = img[0][0].length,i,j;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = img[i][j][2];
            }
        }
    }
    return res;
}


function MergeImageFrom2DTable(R,G,B)
{
    var res = [];
    if (typeof R !== 'undefined' && R !== null && R.length > 0 && R[0].length > 0 && R[0].length > 0 && typeof G !== 'undefined' && G !== null && G.length > 0 && G[0].length > 0 && G[0].length > 0 && typeof B !== 'undefined' && B !== null && B.length > 0 && B[0].length > 0 && B[0].length > 0 && R.length == G.length && R[0].length == G[0].length && R.length == B.length && R[0].length == B[0].length)
    {
        var i,j;
        for (i = 0;i < R.length;i++)
        {
            res[i] = [];
            for (j = 0;j < R[i].length;j++)
            {
		res[i][j] = [];
                res[i][j][0] = R[i][j];
                res[i][j][1] = G[i][j];
                res[i][j][2] = B[i][j];
		res[i][j][3] = 255;
            }
        }
    }
    return res;
}

function MergeImage24bitFormatFrom2DTable(R,G,B)
{
    var res = [];
    if (typeof R !== 'undefined' && R !== null && R.length > 0 && R[0].length > 0 && R[0].length > 0 && typeof G !== 'undefined' && G !== null && G.length > 0 && G[0].length > 0 && G[0].length > 0 && typeof B !== 'undefined' && B !== null && B.length > 0 && B[0].length > 0 && B[0].length > 0 && R.length == G.length && R[0].length == G[0].length && R.length == B.length && R[0].length == B[0].length)
    {
        var i,j;
        for (i = 0;i < R.length;i++)
        {
            res[i] = [];
            for (j = 0;j < R[i].length;j++)
            {
		res[i][j] = 256*256*ValueToUint8(R[i][j]) + 256*ValueToUint8(G[i][j]) + ValueToUint8(B[i][j]);
            }
        }
    }
    return res;
}


function I24bit2Table(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0)
    {
        var i,j,k;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
                res[i][j][0] = Math.floor(img[i][j]/(256*256));
                res[i][j][1] = Math.floor((img[i][j] - res[i][j][0]*256*256)/(256));
                res[i][j][2] = Math.floor(img[i][j] - res[i][j][0]*256*256 - res[i][j][1]*256);
                res[i][j][3] = 255;
            }
        }
        
    }
    return res;
}

function Table2I24bit(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var i,j;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = ValueToUint8(img[i][j][0])*(256*256) + ValueToUint8(img[i][j][1])*(256) + ValueToUint8(img[i][j][2]);
            }
        }
        
    }
    return res;
}

function Table2Byte(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var i,j,k;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
                for (k = 0;k < img[i][j].length;k++)
                {
                    res[i][j][k] = img[i][j][k];
                    if (img[i][j][k] > 255)
                        res[i][j][k] = 255;
                    if (img[i][j][k] < 0)
                        res[i][j][k] = 0;
                }
            }
        }
        
    }
    return res;
}

function Table2IGray(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var i,j;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = img[i][j][0];
            }
        }
        
    }
    return res;
}

function RoundGray(img,digitAfterComma)
{
    var res = [];
    if (digitAfterComma === 'undefined' && digitAfterComma === null)
	digitAfterComma = 0;
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0)
    {
	if (digitAfterComma == 0)
	{
            var i,j;
            for (i = 0;i < img.length;i++)
            {
		res[i] = [];
		for (j = 0;j < img[i].length;j++)
		{
		     res[i][j] = Math.round(img[i][j]);
		}
	    }
	}else
	{
            var i,j,multi = Math.pow(10,digitAfterComma);
            for (i = 0;i < img.length;i++)
            {
		res[i] = [];
		for (j = 0;j < img[i].length;j++)
		{
		     res[i][j] = Math.round(img[i][j]*multi)/multi;
		}
	    }
        }        
    }
    return res;
}

function Table2DToByte(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0)
    {
	var i,j;
	for (i = 0;i < img.length;i++)
	{
	    res[i] = [];
	    for (j = 0;j < img[i].length;j++)
	    {
		res[i][j] = Math.round(img[i][j]);
		if (res[i][j] < 0)
		    res[i][j] = 0;
		if (res[i][j] > 255)
		    res[i][j] = 255;
	    }
	}
    }
    return res;
}


function IGray2Table(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0)
    {
        var i,j;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
                res[i][j][0] = img[i][j];
                res[i][j][1] = img[i][j];
                res[i][j][2] = img[i][j];
            }
        }
        
    }
    return res;
}

function RGB2Gray(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var i,j,k,tmp;
        var n = img[0][0].length;
        if (n > 3)
            n = 3;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
                tmp = 0.299*img[i][j][0] + 0.587*img[i][j][1] + 0.114*img[i][j][2];
                for (k = 0;k < n;k++)
                    res[i][j][k] = tmp;
                res[i][j][3] = 255;
            }
        }
        
    }
    return res;
}

function BrightnessContrast(img,b,c)
{
    var res = [];
    if (typeof b !== 'undefined' && b !== null && typeof c !== 'undefined' && c !== null && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var i,j,k;
        var n = img[0][0].length;
        if (n > 3)
            n = 3;
        
        var m = [];
        for (k = 0;k < n;k++)
            m[k] = 0;

        for (i = 0;i < img.length;i++)
        {
            for (j = 0;j < img[i].length;j++)
            {
                for (k = 0;k < n;k++)
                    m[k] = m[k] + img[i][j][k];
            }
        }
        for (k = 0;k < n;k++)
            m[k] = m[k]/(img.length*img[0].length);
        
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
                for (k = 0;k < n;k++)
                    res[i][j][k] = img[i][j][k] - m[k];
            }
        }
        
        for (k = 0;k < n;k++)
            m[k] = m[k] + c;
        
        for (i = 0;i < img.length;i++)
        {
            for (j = 0;j < img[i].length;j++)
            {
                for (k = 0;k < n;k++)
                    res[i][j][k] = res[i][j][k]*b + m[k];
                res[i][j][3] = 255;
            }
        }
        
    }
    return res;    
}

function Brightness(img,value)
{
    var res = [];
    if (typeof value !== 'undefined' && value !== null && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var i,j,k;
        var n = img[0][0].length;
        if (n > 3)
            n = 3;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
                for (k = 0;k < n;k++)
                    res[i][j][k] = img[i][j][k] + value;
                res[i][j][3] = 255;
            }
        }
        
    }
    return res;
}

function NormalizationGrayImage(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0)
    {
        var i,j,min_ = img[0][0],max_ = img[0][0];
        for (i = 0;i < img.length;i++)
        {
            for (j = 0;j < img[i].length;j++)
            {
		if (min_ > img[i][j])
		    min_ = img[i][j];
		if (max_ < img[i][j])
		    max_ = img[i][j];
	    }
	}
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
		res[i][j] = Math.round(255*(img[i][j] - min_)/(max_ - min_));
	}
        
    }
    return res;
}

function NormalizationWithTresholdGrayImage(img,XL,XR)
{
    var res = [];
    if (typeof XL !== 'undefined' && XL !== null && typeof XR !== 'undefined' && XR !== null && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0)
    {
        var i,j;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
		res[i][j] = Math.round(255*(img[i][j] - XL)/(XR - XL));
	}
        
    }
    return res;
}

function NormalizationColourImage(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
	var imgGray = RGB2Gray(img);
        var n = img[0][0].length;
        var i,j,k,min_ = imgGray[0][0][0],max_ = imgGray[0][0][0];
        for (i = 0;i < img.length;i++)
        {
            for (j = 0;j < img[i].length;j++)
            {
		if (min_ > img[i][j][0])
		    min_ = img[i][j][0];
		if (max_ < img[i][j][0])
		    max_ = img[i][j][0];
	    }
	}
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
                for (k = 0;k < n;k++)
		    res[i][j][k] = Math.round(255*(img[i][j][k] - min_)/(max_ - min_));
                res[i][j][3] = 255;
            }
	}
        
    }
    return res;
}

function NormalizationWithTresholdColourImage(img,XL,XR)
{
    var res = [];
    if (typeof XL !== 'undefined' && XL !== null && typeof XR !== 'undefined' && XR !== null && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var n = img[0][0].length;
        var i,j,k;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
                for (k = 0;k < n;k++)
		    res[i][j][k] = Math.round(255*(img[i][j][k] - XL)/(XR - XL));
                res[i][j][3] = 255;
            }
	}
        
    }
    return res;
}

function NormalizationWithTresholdCalculateXL(hist,treshold)
{
    if (typeof treshold !== 'undefined' && treshold !== null && typeof hist !== 'undefined' && hist !== null && hist.length > 0)
    {
	var i;
	for(i = 0;i < hist.length;i++)
	{
	    if (hist[i] >= treshold)
	    {
		return i;
	    }
	}
	return 255;
    }
    return 0;
}

function NormalizationWithTresholdCalculateXR(hist,treshold)
{
    if (typeof treshold !== 'undefined' && treshold !== null && typeof hist !== 'undefined' && hist !== null && hist.length > 0)
    {
	var i;
	for(i = hist.length - 1;i >= 0;i--)
	{
	    if (hist[i] >= treshold)
	    {
		return i;
	    }
	}
	return 0;
    }
    return 255;
}

function NormalizationWithTresholdColourImageWidtT(img,treshold)
{
    var res = [];
    if (typeof treshold !== 'undefined' && treshold !== null && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
	var img_ = RGB2Gray(img);
	var hist = NormalizedHistogramBW(img_,0);
	if (hist.length > 0)
	{
	    var XL = NormalizationWithTresholdCalculateXL(hist,treshold);
	    var XR = NormalizationWithTresholdCalculateXR(hist,treshold);
            var n = img[0][0].length;
            var i,j,k;
            for (i = 0;i < img.length;i++)
            {
        	res[i] = [];
        	for (j = 0;j < img[i].length;j++)
        	{
		    res[i][j] = [];
		    for (k = 0;k < n;k++)
			res[i][j][k] = Math.round(255*(img[i][j][k] - XL)/(XR - XL));
		    res[i][j][3] = 255;
		}
            }
	}
        
    }
    return res;
}

function NormalizationWithTresholdColourImageWidtT2(img,treshold)
{
    var res = [];
    if (typeof treshold !== 'undefined' && treshold !== null && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
	var hist0 = NormalizedHistogramBW(img,0);
	var hist1 = NormalizedHistogramBW(img,1);
	var hist2 = NormalizedHistogramBW(img,2);
	if (hist0.length > 0 && hist1.length > 0 && hist2.length > 0)
	{
	    var XL = [];
	    XL[0] = NormalizationWithTresholdCalculateXL(hist0,treshold);
	    XL[1] = NormalizationWithTresholdCalculateXL(hist1,treshold);
	    XL[2] = NormalizationWithTresholdCalculateXL(hist2,treshold);
	    var XR = [];
	    XR[0] = NormalizationWithTresholdCalculateXR(hist0,treshold);
	    XR[1] = NormalizationWithTresholdCalculateXR(hist1,treshold);
	    XR[2] = NormalizationWithTresholdCalculateXR(hist2,treshold);
            var n = img[0][0].length;
            var i,j,k;
            for (i = 0;i < img.length;i++)
            {
        	res[i] = [];
        	for (j = 0;j < img[i].length;j++)
        	{
		    res[i][j] = [];
		    for (k = 0;k < n;k++)
			res[i][j][k] = Math.round(255*(img[i][j][k] - XL[k])/(XR[k] - XL[k]));
		    res[i][j][3] = 255;
		}
            }
	}
        
    }
    return res;
}

function LinearFunctionStretchHistogram(img,a,b)
{
    var res = [];
    if (typeof a !== 'undefined' && a !== null && typeof b !== 'undefined' && b !== null && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var n = img[0][0].length;
        var i,j,k;
	for (i = 0;i < img.length;i++)
	{
	    res[i] = [];
	    for (j = 0;j < img[i].length;j++)
	    {
		res[i][j] = [];
		for (k = 0;k < n;k++)
		{
		    res[i][j][k] = Math.round(a*img[i][j][k] + b);
		    if (res[i][j][k] < 0)
			res[i][j][k] = 0;
		    if (res[i][j][k] > 255)
			res[i][j][k] = 255;
		}
		res[i][j][3] = 255;
	    }
	}	
    }
    return res;
}

function LinearFunctionStretchHistogramRGB(img,aR,bR,aG,bG,aB,bB)
{
    var res = [];
    if (typeof aR !== 'undefined' && aR !== null && typeof bR !== 'undefined' && bR !== null && typeof aG !== 'undefined' && aG !== null && typeof bG !== 'undefined' && bG !== null && typeof aB !== 'undefined' && aB !== null && typeof bB !== 'undefined' && bB !== null && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var n = img[0][0].length;
        var i,j,k;
	for (i = 0;i < img.length;i++)
	{
	    res[i] = [];
	    for (j = 0;j < img[i].length;j++)
	    {
		res[i][j] = [];
		res[i][j][0] = Math.round(aR*img[i][j][0] + bR);
		res[i][j][1] = Math.round(aG*img[i][j][1] + bG);
		res[i][j][2] = Math.round(aB*img[i][j][2] + bB);
		for (k = 0;k < n;k++)
		{
		    if (res[i][j][k] < 0)
			res[i][j][k] = 0;
		    if (res[i][j][k] > 255)
			res[i][j][k] = 255;
		}
		res[i][j][3] = 255;
	    }
	}	
    }
    return res;
}

function NonLinearFunctionStretchHistogramxA(img,a)
{
    var res = [];
    if (typeof a !== 'undefined' && a !== null && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var n = img[0][0].length;
        var i,j,k,tmp = Math.pow(2,8*(a-1));
	for (i = 0;i < img.length;i++)
	{
	    res[i] = [];
	    for (j = 0;j < img[i].length;j++)
	    {
		res[i][j] = [];
		for (k = 0;k < n;k++)
		{
		    res[i][j][k] = Math.pow(img[i][j][k],a)/tmp;
		}
		res[i][j][3] = 255;
	    }
	}
//	res = NormalizationColourImage(res);
    }
    return res;
}

function SumTable(tab)
{
    var s = 0;
    if (tab !== 'undefined' && tab !== null && tab.length > 0)
    {
        var i;
	for (i = 0;i < tab.length;i++)
	    s = s + tab[i];
    }
    return s;
}

function SumTable2D(tab)
{
    var s = 0;
    if (tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
        var i,j;
	for (i = 0;i < tab.length;i++)
	    for (j = 0;j < tab[i].length;j++)
	    	s = s + tab[i][j];
    }
    return s;
}


function MeanTable(tab)
{
    var m = 0;
    if (tab !== 'undefined' && tab !== null && tab.length > 0)
    {
        m = SumTable(tab)/tab.length;
    }
    return m;
}

function MeanTable2D(tab)
{
    var m = 0;
    if (tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var n = tab.length*tab[0].length;
        m = SumTable2D(tab)/n;
    }
    return m;
}

function RoundValue(v,n)
{
    if (n == 'undefined' || n == null || n < 0)
	n = 0;
    if (v !== 'undefined' && v !== null)
    {
	var tmp = Math.pow(10,n);
	return Math.round(tmp*v)/tmp;
    }
    return 0;
}

function ValueToUint8(v)
{
    if (v !== 'undefined' && v !== null)
    {
	var tmp = Math.round(v);
	if (tmp < 0)
	    return 0;
	if (tmp > 255)
	    return 255;
	return tmp;
    }
    return 0;
}


function EqualizationHistogramIntervals(hist)
{
    var res = [];
    if (hist !== 'undefined' && hist !== null && hist.length > 0)
    {
	var i,tmp = [];
        m = MeanTable(hist);
	for(i = 0;i < hist.length;i++)
	    tmp[i] = hist[i]/m;
	res[0] = 0;
	for(i = 0;i < hist.length;i++)
	    res[i+1] = res[i] + tmp[i];
    }
    return res;
}

function EqualizationHistogramIntervalsNo(hist,no)
{
    if (no !== 'undefined' && no !== null && no >= 0 && hist !== 'undefined' && hist !== null && hist.length > 0)
    {
    	var res = [];
	var i,tmp = [];
        var m = MeanTable(hist);
	for(i = 0;i < hist.length;i++)
	    tmp[i] = hist[i]/m;
	res[0] = 0;
	for(i = 0;i < hist.length;i++)
	    res[i+1] = res[i] + tmp[i];
	return res[no];
    }
    return 0;
}


function EqualizationWidthIntervals(img,no)
{
    if (no !== 'undefined' && no !== null && no >= 0 && img !== 'undefined' && img !== null && img.length > 0)
    {
	var hist = HistogramNValues(img,no)
   	if (hist !== 'undefined' && hist !== null && hist.length > 0 && hist[0].length > 0)
	{
	    var i,res = [];
            var m = MeanTable2D(hist);
	    res[0] = [];
	    for(i = 0;i < hist[0].length;i++)
//	        res[0][i] = hist[0][i]*(no-1)/(m*no);
	        res[0][i] = hist[0][i]/m;
	    return res;
	}
    }
    return [];
}

function EqualizationBorderIntervals(img,no)
{
    if (no !== 'undefined' && no !== null && no >= 0 && img !== 'undefined' && img !== null && img.length > 0)
    {
	var widthInterval = EqualizationWidthIntervals(img,no)
   	if (widthInterval !== 'undefined' && widthInterval !== null && widthInterval.length > 0 && widthInterval[0].length > 0)
	{
	    var i,res = [];
	    res[0] = [];
	    res[0][0] = -0.5;
	    for(i = 0;i < widthInterval[0].length;i++)
	        res[0][i + 1] = res[0][i] + widthInterval[0][i];
	    return res;
	}
    }
    return [];
}

function EqualizationHistogramGrayImage(img,no)
{
    if (no !== 'undefined' && no !== null && no >= 0 && img !== 'undefined' && img !== null && img.length > 0)
    {
	var border = EqualizationBorderIntervals(img,no)
   	if (border !== 'undefined' && border !== null && border.length > 0 && border[0].length > 0)
	{
	    var i,j,res = [],tmp;
	    for(i = 0;i < img.length;i++)
	    {
		res[i] = [];
	    	for(j = 0;j < img[i].length;j++)
		{
		    tmp = Math.round(img[i][j]);
	            res[i][j] = (border[0][tmp] + border[0][tmp+1])/2;
		}
	    }
	    return res;
	}
    }
    return [];
}

function EqualizationHistogramColourImage(img)
{
    if (img !== 'undefined' && img !== null && img.length > 0)
    {
	var grayImage = RGB2Gray(img);
	var hist = HistogramBW(img,0);
	var m = MeanTable(hist);
	var i,intervals = [];
    	for(i = 0;i < hist.length;i++)
            intervals[i] = hist[i]/m;

	var border = [];
    	border[0] = -0.5;
	for(i = 0;i < intervals.length;i++)
	    border[i + 1] = border[i] + intervals[i];
	
   	if (border !== 'undefined' && border !== null && border.length > 0)
	{
	    var j,k,res = [],tmp;
	    for(i = 0;i < img.length;i++)
	    {
		res[i] = [];
	    	for(j = 0;j < img[i].length;j++)
		{
		    res[i][j] = [];
		    for(k = 0;k < img[i][j].length;k++)
		    {
		        tmp = Math.round(img[i][j][k]);
		        res[i][j][k] = (border[tmp] + border[tmp+1])/2;
		    }
		}
	    }
	    return res;
	}
    }
    return [];
}


function Table2D2Range(tab,no)
{
    if (no !== 'undefined' && no !== null && no >= 0 && tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var i,j,res = [];
	for(i = 0;i < tab.length;i++)
	{
	    res[i] = [];
	    for(j = 0;j < tab[i].length;j++)
	    {
		res[i][j] = tab[i][j];
		if (res[i][j] < 0)
		    res[i][j] = 0;
		if (res[i][j] > no)
		    res[i][j] = no;
	    }
	}
	return res;
    }
    return [];
}

function Histogram2DTable(tab,maxValue,d,alpha) {
    if (d !== 'undefined' && d !== null && d > 0 && alpha !== 'undefined' && alpha !== null  && maxValue !== 'undefined' && maxValue !== null && maxValue > 0 && tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var i,j,k, res = [],v1,v2,dx,dy,alphaRad = alpha*Math.PI/180,x,y;

	dx = d*Math.cos(alphaRad);
	dy = d*Math.sin(alphaRad);

	for (i = 0;i <= maxValue;i++)
	{
	    res[i] = [];
	    for (j = 0;j <= maxValue;j++)
		res[i][j] = 0;
	}

	for (i = 0;i < tab.length;i++)
	{
	    for (j = 0;j < tab[i].length;j++)
	    {
		v1 = tab[i][j];
		x = Math.round(j + dx);
		y = Math.round(i + dy);
		if (x >= 0 && x < tab[i].length && y >= 0 && y < tab.length)
		{
		    v2 = tab[y][x];
		    res[Math.round(v2)][Math.round(v1)]++;
		}
	    }
	}
	return res;
    }
    return [];
}

function Histogram2DColourImage(img,maxValue,d,alpha) {
    if (d !== 'undefined' && d !== null && d > 0 && alpha !== 'undefined' && alpha !== null  && maxValue !== 'undefined' && maxValue !== null && maxValue > 0 && img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0)
    {
	var i,j,k, res = [],v1,v2,dx,dy,alphaRad = alpha*Math.PI/180,x,y;

	dx = d*Math.cos(alphaRad);
	dy = d*Math.sin(alphaRad);


	for (i = 0;i <= maxValue;i++)
	{
	    res[i] = [];
	    for (j = 0;j <= maxValue;j++)
	    {
		res[i][j] = [];
		for (k = 0;k < img[0][0].length - 1;k++)
		    res[i][j][k] = 0;
		res[i][j][3] = 255;
	    }
	}

	for (i = 0;i < img.length;i++)
	{
	    for (j = 0;j < img[i].length;j++)
	    {
		for (k = 0;k < img[i][j].length-1;k++)
		{
		    v1 = img[i][j][k];
		    x = Math.round(j + dx);
		    y = Math.round(i + dy);
		    if (x >= 0 && x < img[i].length && y >= 0 && y < img.length)
		    {
			v2 = img[y][x][k];
			res[Math.round(v2)][Math.round(v1)][k]++;
		    }
		}
	    }
	}
	return res;
    }
    return [];
}


function NormalizationHistogram2D(img,width,height,norm) {
    if (width !== 'undefined' && width !== null && width > 0 && height !== 'undefined' && height !== null && height > 0 && norm !== 'undefined' && norm !== null && norm > 0 && img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0)
    {
	var i,j,k,res = [],tmp = norm/(width*height);

	for (i = 0;i < img.length;i++)
	{
	    res[i] = [];
	    for (j = 0;j < img[i].length;j++)
	    {
		res[i][j] = [];
		for (k = 0;k < img[i][j].length-1;k++)
		{
		    res[i][j][k] = tmp*img[i][j][k];
		}
		res[i][j][3] = 255;
	    }
	}
	return res;
    }
    return [];
}


function Tresholding2DTable(tab,t)
{
    var res = [];
    if (t !== 'undefined' && t !== null && t >= 0 && t <= 255 && typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
        var i,j;
        for (i = 0;i < tab.length;i++)
        {
            res[i] = [];
            for (j = 0;j < tab[i].length;j++)
            {
		if (tab[i][j] <= t)
                    res[i][j] = 0;
		else
                    res[i][j] = 1;
            }
        }
        
    }
    return res;
}


function Tresholding(img,t)
{
    var res = [];
    if (t !== 'undefined' && t !== null && t >= 0 && t <= 255 && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var i,j,k;
        var n = img[0][0].length;
        if (n > 3)
            n = 3;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
                for (k = 0;k < n;k++)
		    if (img[i][j][k] <= t)
                	res[i][j][k] = 0;
		    else
                	res[i][j][k] = 255;
                res[i][j][3] = 255;
            }
        }
        
    }
    return res;
}

function TresholdingInvertBinary(img,t)
{
    var res = [];
    if (t !== 'undefined' && t !== null && t >= 0 && t <= 255 && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var i,j,k;
        var n = img[0][0].length;
        if (n > 3)
            n = 3;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
                for (k = 0;k < n;k++)
		    if (img[i][j][k] > t)
                	res[i][j][k] = 0;
		    else
                	res[i][j][k] = 255;
                res[i][j][3] = 255;
            }
        }
        
    }
    return res;
}

function TresholdingInvertBinary2DTable(tab,t)
{
    var res = [];
    if (t !== 'undefined' && t !== null && t >= 0 && t <= 255 && typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
        var i,j;
        for (i = 0;i < tab.length;i++)
        {
            res[i] = [];
            for (j = 0;j < tab[i].length;j++)
            {
		if (tab[i][j] > t)
                    res[i][j] = 0;
		else
                    res[i][j] = 1;
            }
        }
        
    }
    return res;
}


function TresholdingIntervalBinary(img,t0,t1)
{
    var res = [];
    if (t0 !== 'undefined' && t0 !== null && t0 >= 0 && t0 <= 255 && t1 !== 'undefined' && t1 !== null && t1 >= 0 && t1 <= 255 && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var i,j,k;
        var n = img[0][0].length;
        if (n > 3)
            n = 3;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
                for (k = 0;k < n;k++)
		    if (img[i][j][k] >= t0 && img[i][j][k] <= t1)
                	res[i][j][k] = 255;
		    else
                	res[i][j][k] = 0;
                res[i][j][3] = 255;
            }
        }
        
    }
    return res;
}

function TresholdingIntervalBinary2DTable(tab,t0,t1)
{
    var res = [];
    if (t0 !== 'undefined' && t0 !== null && t0 >= 0 && t0 <= 255 && t1 !== 'undefined' && t1 !== null && t1 >= 0 && t1 <= 255  && typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
        var i,j;
        for (i = 0;i < tab.length;i++)
        {
            res[i] = [];
            for (j = 0;j < tab[i].length;j++)
            {
		if (tab[i][j] >= t0 && tab[i][j] <= t1)
                    res[i][j] = 1;
		else
                    res[i][j] = 0;
            }
        }
        
    }
    return res;
}


function TresholdingIntervalInvertBinary2DTable(tab,t0,t1)
{
    var res = [];
    if (t0 !== 'undefined' && t0 !== null && t0 >= 0 && t0 <= 255 && t1 !== 'undefined' && t1 !== null && t1 >= 0 && t1 <= 255  && typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
        var i,j;
        for (i = 0;i < tab.length;i++)
        {
            res[i] = [];
            for (j = 0;j < tab[i].length;j++)
            {
		if (tab[i][j] > t0 && tab[i][j] < t1)
                    res[i][j] = 0;
		else
                    res[i][j] = 1;
            }
        }
        
    }
    return res;
}


function TresholdingIntervalInvertBinary(img,t0,t1)
{
    var res = [];
    if (t0 !== 'undefined' && t0 !== null && t0 >= 0 && t0 <= 255 && t1 !== 'undefined' && t1 !== null && t1 >= 0 && t1 <= 255 && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var i,j,k;
        var n = img[0][0].length;
        if (n > 3)
            n = 3;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
                for (k = 0;k < n;k++)
		    if (img[i][j][k] > t0 && img[i][j][k] < t1)
                	res[i][j][k] = 0;
		    else
                	res[i][j][k] = 255;
                res[i][j][3] = 255;
            }
        }
        
    }
    return res;
}

function TresholdingIntervalBinaryValue(v,t0,t1)
{
    var res = null;
    if (t0 !== 'undefined' && t0 !== null && t0 >= 0 && t0 <= 255 && t1 !== 'undefined' && t1 !== null && t1 >= 0 && t1 <= 255  && typeof v !== 'undefined' && v !== null)
    {
	if (v >= t0 && v <= t1)
            res = 1;
	else
            res = 0;
    }
    return res;
}

function TresholdingIntervalBinaryValue2(vR,vG,vB,tR0,tR1,tG0,tG1,tB0,tB1)
{
    var res = null;
    if (typeof vR !== 'undefined' && vR !== null && typeof vG !== 'undefined' && vG !== null && typeof vB !== 'undefined' && vB !== null)
    {
	var rR = TresholdingIntervalBinaryValue(vR,tR0,tR1);
	var rG = TresholdingIntervalBinaryValue(vG,tG0,tG1);
	var rB = TresholdingIntervalBinaryValue(vB,tB0,tB1);
	if (rR != null && rG != null && rB != null)
	{
	    if (rR == 1 && rG == 1 && rB == 1)
        	res = 1;
	    else
        	res = 0;
	}
    }
    return res;
}

function TresholdingIntervalBinaryColourImage(img,tR0,tR1,tG0,tG1,tB0,tB1)
{
    var res = [];
    if (tR0 !== 'undefined' && tR0 !== null && tR0 >= 0 && tR0 <= 255 && tR1 !== 'undefined' && tR1 !== null && tR1 >= 0 && tR1 <= 255 && tG0 !== 'undefined' && tG0 !== null && tG0 >= 0 && tG0 <= 255 && tG1 !== 'undefined' && tG1 !== null && tG1 >= 0 && tG1 <= 255 && tB0 !== 'undefined' && tB0 !== null && tB0 >= 0 && tB0 <= 255 && tB1 !== 'undefined' && tB1 !== null && tB1 >= 0 && tB1 <= 255 && typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
        var i,j,o = [];
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
                res[i][j] = [];
		if (img[i][j][0] >= tR0 && img[i][j][0] <= tR1)
		    o[0] = 1;
		else
		    o[0] = 0;
		if (img[i][j][1] >= tG0 && img[i][j][1] <= tG1)
		    o[1] = 1;
		else
		    o[1] = 0;
		if (img[i][j][2] >= tB0 && img[i][j][2] <= tB1)
		    o[2] = 1;
		else
		    o[2] = 0;
		if (o[0] == 1 && o[1] == 1 && o[2] == 1)
		{
		   res[i][j][0] = 255;
		   res[i][j][1] = 255;
		   res[i][j][2] = 255;
		}else
		{
		   res[i][j][0] = 0;
		   res[i][j][1] = 0;
		   res[i][j][2] = 0;
		}
                res[i][j][3] = 255;
            }
        }
        
    }
    return res;
}

function MultiLevelThresholding2DTable(img,t,b)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && typeof t !== 'undefined' && t !== null && t.length > 0 && t[0].length > 0 && t[0].length > 0 && typeof b !== 'undefined' && b !== null && b.length > 0 && b[0].length > 0 && b[0].length > 0 && b[0].length == t[0].length + 1)
    {
        var i,j,k;
	var nb = b[0].length;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
		res[i][j] =  b[0][nb-1];
                for (k = nb-2;k >= 0;k--)
		{
		    if (img[i][j] <= t[0][k])
			res[i][j] = b[0][k];
		    else
			break;
		}
            }
        }      
    }
    return res;
}

function MultiLevelThresholdingImage(img,t,b)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && img[0][0].length > 0 && typeof t !== 'undefined' && t !== null && t.length > 0 && t[0].length > 0 && t[0].length > 0 && typeof b !== 'undefined' && b !== null && b.length > 0 && b[0].length > 0 && b[0].length > 0 && b[0].length == t[0].length + 1)
    {
        var i,j,k,l;
	var nb = b[0].length;
        var n = img[0][0].length;
        if (n > 3)
            n = 3;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
            {
		res[i][j] = [];
                for (l = 0;l < n;l++)
		{
		    res[i][j][l] =  b[0][nb-1];
                    for (k = nb-2;k >= 0;k--)
		    {
			if (img[i][j][l] <= t[0][k])
			    res[i][j][l] = b[0][k];
			else
			    break;
		    }
		}
		res[i][j][3] = 255;
            }
        }      
    }
    return res;
}

function AddingTwo2dTables(img0,img1,w0,w1)
{
    var res = [];
    if (typeof img0 !== 'undefined' && img0 !== null && img0.length > 0 && img0[0].length > 0  && typeof img1 !== 'undefined' && img1 !== null && img1.length > 0 && img1[0].length > 0  && img0.length == img1.length && img0[0].length == img1[0].length && typeof w0 !== 'undefined' && w0 !== null && typeof w1 !== 'undefined' && w1 !== null)
    {
        var i,j;
        for (i = 0;i < img0.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img0[i].length;j++)
            {
		res[i][j] = w0*img0[i][j] + w1*img1[i][j];
            }
        }      
    }
    return res;
}

function AddingTwoImages(img0,img1,w0,w1)
{
    var res = [];
    if (typeof img0 !== 'undefined' && img0 !== null && img0.length > 0 && img0[0].length > 0  && img0[0][0].length > 0 && typeof img1 !== 'undefined' && img1 !== null && img1.length > 0 && img1[0].length > 0  && img1[0][0].length > 0 && img0[0][0].length == img1[0][0].length && typeof w0 !== 'undefined' && w0 !== null && typeof w1 !== 'undefined' && w1 !== null)
    {
        var i,j;
	var n = img0.length;
	if (n > img1.length)
	    n = img1.length
	var m = img0[0].length;
	if (m > img1[0].length)
	    m = img1[0].length
        var n2 = img0[0][0].length;
        if (n2 > 3)
            n2 = 3;
        for (i = 0;i < n;i++)
        {
            res[i] = [];
            for (j = 0;j < m;j++)
            {
		res[i][j] = [];
            	for (k = 0;k < n2;k++)
		{
		    res[i][j][k] = w0*img0[i][j][k] + w1*img1[i][j][k];
		}
		res[i][j][3] = 255;
            }
        }      
    }
    return res;
}

function SubtractionTwo2dTables(img0,img1)
{
    var res = [];
    if (typeof img0 !== 'undefined' && img0 !== null && img0.length > 0 && img0[0].length > 0  && typeof img1 !== 'undefined' && img1 !== null && img1.length > 0 && img1[0].length > 0  && img0.length == img1.length && img0[0].length == img1[0].length)
    {
        var i,j;
        for (i = 0;i < img0.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img0[i].length;j++)
            {
		res[i][j] = Math.abs(img0[i][j] - img1[i][j]);
            }
        }      
    }
    return res;
}

function SubtractionTwoImages(img0,img1)
{
    var res = [];
    if (typeof img0 !== 'undefined' && img0 !== null && img0.length > 0 && img0[0].length > 0  && img0[0][0].length > 0 && typeof img1 !== 'undefined' && img1 !== null && img1.length > 0 && img1[0].length > 0  && img1[0][0].length > 0 && img0[0][0].length == img1[0][0].length)
    {
        var i,j;
	var n = img0.length;
	if (n > img1.length)
	    n = img1.length
	var m = img0[0].length;
	if (m > img1[0].length)
	    m = img1[0].length
        var n2 = img0[0][0].length;
        if (n2 > 3)
            n2 = 3;
        for (i = 0;i < n;i++)
        {
            res[i] = [];
            for (j = 0;j < m;j++)
            {
		res[i][j] = [];
            	for (k = 0;k < n2;k++)
		{
		    res[i][j][k] = Math.abs(img0[i][j][k] - img1[i][j][k]);
		}
		res[i][j][3] = 255;
            }
        }      
    }
    return res;
}


function DuplicateTexture(img,w,h)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0  && img[0][0].length > 0 && typeof w !== 'undefined' && w !== null && w > 0 && typeof h !== 'undefined' && h !== null && h > 0)
    {
        var i,j,k,ii,iii,jj,jjj,n,nn,m,mm;
        var n2 = img[0][0].length;
        if (n2 > 3)
            n2 = 3;
	n = img.length;
	nn = Math.ceil(w/n);
	m = img[0].length;
	mm = Math.ceil(h/m);
	for (ii = 0,iii = 0;ii < nn;ii++)
	{
	    for (i = 0;i < n && iii < w;i++,iii++)
	    {
	    	res[iii] = [];
		for (jj = 0,jjj = 0;jj < mm;jj++)
		{
		    for (j = 0;j < m && jjj < h;j++,jjj++)
		    {
			res[iii][jjj] = [];
			for (k = 0;k < n2;k++)
			{
			    res[iii][jjj][k] = img[i][j][k];
			}
			res[iii][jjj][3] = 255;
		    }
		}
            }
        }      
    }
    return res;
}


function ShiftTableDown2DTable(img,shiftT,value)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && typeof shiftT !== 'undefined' && shiftT !== null && typeof value !== 'undefined' && value !== null)
    {
        var i,j,start = shiftT;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
		res[i][j] = value;
	} 

        for (i = start;i < img.length;i++)
        {
            for (j = 0;j < img[i].length;j++)
            {
		res[i][j] =  img[i - shiftT][j];
            }
        }      
    }
    return res;
}

function ShiftTableRight2DTable(img,shiftT,value)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && typeof shiftT !== 'undefined' && shiftT !== null && typeof value !== 'undefined' && value !== null)
    {
        var i,j,start = shiftT;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
		res[i][j] = value;
	} 

        for (i = 0;i < img.length;i++)
        {
            for (j = start;j < img[i].length;j++)
            {
		res[i][j] =  img[i][j - shiftT];
            }
        }      
    }
    return res;
}

function XORTable2DTable(img,img2)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && typeof img2 !== 'undefined' && img2 !== null && img2.length > 0 && img2[0].length > 0 && img2[0].length > 0 && img.length == img2.length && img[0].length == img2[0].length)
    {
        var i,j;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
		if (img[i][j] == img2[i][j])
		    res[i][j] = 0;
		else
		    res[i][j] = 1;
	} 

    }
    return res;
}


function ANDTable2DTable(img,img2)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && typeof img2 !== 'undefined' && img2 !== null && img2.length > 0 && img2[0].length > 0 && img2[0].length > 0 && img.length == img2.length && img[0].length == img2[0].length)
    {
        var i,j;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
		if (img[i][j] == 1 && img2[i][j] == 1)
		    res[i][j] = 1;
		else
		    res[i][j] = 0;
	} 

    }
    return res;
}

function ORTable2DTable(img,img2)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && typeof img2 !== 'undefined' && img2 !== null && img2.length > 0 && img2[0].length > 0 && img2[0].length > 0 && img.length == img2.length && img[0].length == img2[0].length)
    {
        var i,j;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
		if (img[i][j] == 1 || img2[i][j] == 1)
		    res[i][j] = 1;
		else
		    res[i][j] = 0;
	} 

    }
    return res;
}

function Multiple2DImage(img,value)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 &&  typeof value !== 'undefined' && value !== null)
    {
        var i,j;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
		res[i][j] = img[i][j]*value;
	} 

    }
    return res;
}

function SumValueTo2DImage(img,value)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 &&  typeof value !== 'undefined' && value !== null)
    {
        var i,j;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
		res[i][j] = img[i][j] + value;
	} 

    }
    return res;
}

function MultipleImageByValue(img,value)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0 && typeof value !== 'undefined' && value !== null)
    {
        var i,j,k;
        for (i = 0;i < img.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img[i].length;j++)
	    {
		res[i][j] = [];
		for (k = 0;k < img[i][j].length;k++)
		{
		    res[i][j][k] = img[i][j][k]*value;
		}
	    }
	} 

    }
    return res;
}

function Multiple2DTable(img0,img1)
{
    var res = [];
    if (typeof img0 !== 'undefined' && img0 !== null && img0.length > 0 && img0[0].length > 0 && img0[0].length > 0 && typeof img1 !== 'undefined' && img1 !== null && img1.length > 0 && img1[0].length > 0 && img1[0].length > 0 && img0.length == img1.length && img0[0].length == img1[0].length)
    {
        var i,j;
        for (i = 0;i < img0.length;i++)
        {
            res[i] = [];
            for (j = 0;j < img0[i].length;j++)
		res[i][j] = img0[i][j]*img1[i][j];
	} 

    }
    return res;
}


function LogicalContour(img,value)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0 && typeof value !== 'undefined' && value !== null)
    {
	var R = GetR2DTable(img);
	var G = GetG2DTable(img);
	var B = GetB2DTable(img);

	R = Tresholding2DTable(R,value);
	G = Tresholding2DTable(G,value);
	B = Tresholding2DTable(B,value);

	var R0 = ShiftTableDown2DTable(R,1,1);
	var R1 = ShiftTableRight2DTable(R,1,1);
	R0 = XORTable2DTable(R0,R);
	R1 = XORTable2DTable(R1,R);
	R =  ORTable2DTable(R0,R1);

	var G0 = ShiftTableDown2DTable(G,1,1);
	var G1 = ShiftTableRight2DTable(G,1,1);
	G0 = XORTable2DTable(G0,G);
	G1 = XORTable2DTable(G1,G);
	G =  ORTable2DTable(G0,G1);

	var B0 = ShiftTableDown2DTable(B,1,1);
	var B1 = ShiftTableRight2DTable(B,1,1);
	B0 = XORTable2DTable(B0,B);
	B1 = XORTable2DTable(B1,B);
	B =  ORTable2DTable(B0,B1);

	R = Multiple2DImage(R,255);
	G = Multiple2DImage(G,255);
	B = Multiple2DImage(B,255);

	res = MergeImageFrom2DTable(R,G,B);
        
    }
    return res;
}

function ConvolutionFilter2DTable(img,mask,norm)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && typeof mask !== 'undefined' && mask !== null && mask.length > 0 && mask[0].length > 0 && mask[0].length > 0 && typeof norm !== 'undefined' && norm !== null)
    {
	
        var i,j,k0,k1,s;
	var sX = (mask.length - 1)/2;
	var sY = (mask[0].length - 1)/2;
	var sXa = Math.floor(sX),sYa = Math.floor(sY);
	var sXb = Math.ceil(sX),sYb = Math.ceil(sY);

        for (i = sXa;i < img.length - sXb;i++)
        {
            res[i - sXa] = [];
            for (j = sYa;j < img[i].length - sYb;j++)
	    {
		s = 0;
	        for (k0 = 0;k0 < mask.length;k0++)
		    for (k1 = 0;k1 < mask[0].length;k1++)
			s = s + img[i + k0 - sXa][j + k1 - sYa]*mask[k0][k1];
		res[i - sXa][j - sYa] = s/norm;
	    }
	} 

	return res;
    }
    return res;
}

function ConvolutionFilter(img,mask,norm)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0 && typeof mask !== 'undefined' && mask !== null && mask.length > 0 && mask[0].length > 0 && mask[0].length > 0 && typeof norm !== 'undefined' && norm !== null)
    {
	var R = GetR2DTable(img);
	var G = GetG2DTable(img);
	var B = GetB2DTable(img);

	R = Table2DToByte(ConvolutionFilter2DTable(R,mask,norm));
	G = Table2DToByte(ConvolutionFilter2DTable(G,mask,norm));
	B = Table2DToByte(ConvolutionFilter2DTable(B,mask,norm));

	res = MergeImageFrom2DTable(R,G,B);

	return res;
    }
    return res;
}


function CutImage(img,x0,y0,x1,y1)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0 && typeof x0 !== 'undefined' && x0 !== null && typeof y0 !== 'undefined' && y0 !== null && typeof x1 !== 'undefined' && x1 !== null && typeof y1 !== 'undefined' && y1 !== null)
    {

	x0 = Math.round(x0*img.length);	
	x1 = Math.round(x1*img.length);	

	y0 = Math.round(y0*img[0].length);	
	y1 = Math.round(y1*img[0].length);	

	var tmp;
	if (x0 < 0)
	    x0 = 0;
	if (x0 >= img.length)
	    x0 = img.length - 1;
	if (y0 < 0)
	    y0 = 0;
	if (y0 >= img[0].length)
	    y0 = img[0].length - 1;
	if (x1 < 0)
	    x1 = 0;
	if (x1 >= img.length)
	    x1 = img.length - 1;
	if (y1 < 0)
	    y1 = 0;
	if (y1 >= img[0].length)
	    y1 = img[0].length - 1;

	if (x0 > x1)
	{
	    tmp = x0;
	    x0 = x1;
	    x1 = tmp;
	}
	if (y0 > y1)
	{
	    tmp = y0;
	    y0 = y1;
	    y1 = tmp;
	}

        var n = img[0][0].length;
        var i,j,k,ii,jj;
        for (i = x0,ii = 0;i < x1;i++,ii++)
        {
            res[ii] = [];
            for (j = y0,jj = 0;j < y1;j++,jj++)
            {
                res[ii][jj] = [];
                for (k = 0;k < n;k++)
		    res[ii][jj][k] = img[i][j][k];
                res[ii][jj][3] = 255;
            }
	}
        
    }
    return res;
}


function IncreaseImage(img,value)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0 && typeof value !== 'undefined' && value !== null)
    {


        var n = img[0][0].length;
        var i,j,k,ii,jj,iii,jjj;
        for (i = 0,ii = 0;i < img.length;i++)
        {
	    for (iii = 0;iii < value;iii++,ii++)
	    {
		res[ii] = [];
		for (j = 0,jj = 0;j < img[0].length;j++)
		{
		    for (jjj = 0;jjj < value;jjj++,jj++)
		    {
			res[ii][jj] = [];
			for (k = 0;k < n;k++)
			    res[ii][jj][k] = img[i][j][k];
			res[ii][jj][3] = 255;
		    }
		}
            }
	}
        
    }
    return res;
}

function Table2DTo1D(tab)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
        var i,j,k;
        for (i = 0,k = 0;i < tab.length;i++)
        {
            for (j = 0;j < tab[i].length;j++,k++)
		res[k] = tab[i][j];
	} 
    }
    return res;
}

function MedianTable1D(tab)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0)
    {
        var tmp = tab.sort((a, b) => a - b);
	var n = tab.length;
	res = tmp[(n - 1)/2];
    }
    return res;
}

function MedianFilter2DTable(img,mask)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && typeof mask !== 'undefined' && mask !== null)
    {
	
        var i,j,k0,k1,s,tmp,k;
	var sX = (mask - 1)/2;
	var sY = (mask - 1)/2;

        for (i = sX;i < img.length - sX;i++)
        {
            res[i - sX] = [];
            for (j = sY;j < img[i].length - sY;j++)
	    {
		s = 0;
		tmp = [];
	        for (k0 = 0,k = 0;k0 < mask;k0++)
		    for (k1 = 0;k1 < mask;k1++,k++)
			tmp[k] = img[i + k0 - sX][j + k1 - sY];

		res[i - sX][j - sY] = MedianTable1D(tmp);
	    }
	} 

	return res;
    }
    return res;
}

function MedianStrongFilter2DTable(img,mask)
{
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && typeof mask !== 'undefined' && mask !== null)
    {
	
        var i,j,k0,k1,s,tmp,k;
	var sX = (mask - 1)/2;
	var sY = (mask - 1)/2;

        for (i = sX;i < img.length - sX;i++)
        {
            for (j = sY;j < img[i].length - sY;j++)
	    {
		s = 0;
		tmp = [];
	        for (k0 = 0,k = 0;k0 < mask;k0++)
		    for (k1 = 0;k1 < mask;k1++,k++)
			tmp[k] = img[i + k0 - sX][j + k1 - sY];

		img[i][j] = MedianTable1D(tmp);
	    }
	} 

	return img;
    }
    return img;
}

function MedianFilter(img,mask)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0 && typeof mask !== 'undefined' && mask !== null)
    {
	var R = GetR2DTable(img);
	var G = GetG2DTable(img);
	var B = GetB2DTable(img);

	R = Table2DToByte(MedianFilter2DTable(R,mask));
	G = Table2DToByte(MedianFilter2DTable(G,mask));
	B = Table2DToByte(MedianFilter2DTable(B,mask));

	res = MergeImageFrom2DTable(R,G,B);

	return res;
    }
    return res;
}

function MedianStrongFilter(img,mask)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0 && typeof mask !== 'undefined' && mask !== null)
    {
	var R = GetR2DTable(img);
	var G = GetG2DTable(img);
	var B = GetB2DTable(img);

	R = Table2DToByte(MedianStrongFilter2DTable(R,mask));
	G = Table2DToByte(MedianStrongFilter2DTable(G,mask));
	B = Table2DToByte(MedianStrongFilter2DTable(B,mask));

	res = MergeImageFrom2DTable(R,G,B);

	return res;
    }
    return res;
}

function MinFilter2DTable(img,mask)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && typeof mask !== 'undefined' && mask !== null)
    {
	
        var i,j,k0,k1,s,tmp,k;
	var sX = (mask - 1)/2;
	var sY = (mask - 1)/2;

        for (i = sX;i < img.length - sX;i++)
        {
            res[i - sX] = [];
            for (j = sY;j < img[i].length - sY;j++)
	    {
		s = 0;
		tmp = [];
	        for (k0 = 0,k = 0;k0 < mask;k0++)
		    for (k1 = 0;k1 < mask;k1++,k++)
			tmp[k] = img[i + k0 - sX][j + k1 - sY];

		res[i - sX][j - sY] = Math.min.apply(null,(tmp));
	    }
	} 

	return res;
    }
    return res;
}

function MinFilter(img,mask)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0 && typeof mask !== 'undefined' && mask !== null)
    {
	var R = GetR2DTable(img);
	var G = GetG2DTable(img);
	var B = GetB2DTable(img);

	R = Table2DToByte(MinFilter2DTable(R,mask));
	G = Table2DToByte(MinFilter2DTable(G,mask));
	B = Table2DToByte(MinFilter2DTable(B,mask));

	res = MergeImageFrom2DTable(R,G,B);

	return res;
    }
    return res;
}

function MaxFilter2DTable(img,mask)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && typeof mask !== 'undefined' && mask !== null)
    {
	
        var i,j,k0,k1,s,tmp,k;
	var sX = (mask - 1)/2;
	var sY = (mask - 1)/2;

        for (i = sX;i < img.length - sX;i++)
        {
            res[i - sX] = [];
            for (j = sY;j < img[i].length - sY;j++)
	    {
		s = 0;
		tmp = [];
	        for (k0 = 0,k = 0;k0 < mask;k0++)
		    for (k1 = 0;k1 < mask;k1++,k++)
			tmp[k] = img[i + k0 - sX][j + k1 - sY];

		res[i - sX][j - sY] = Math.max.apply(null,(tmp));
	    }
	} 

	return res;
    }
    return res;
}

function MaxFilter(img,mask)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0 && typeof mask !== 'undefined' && mask !== null)
    {
	var R = GetR2DTable(img);
	var G = GetG2DTable(img);
	var B = GetB2DTable(img);

	R = Table2DToByte(MaxFilter2DTable(R,mask));
	G = Table2DToByte(MaxFilter2DTable(G,mask));
	B = Table2DToByte(MaxFilter2DTable(B,mask));

	res = MergeImageFrom2DTable(R,G,B);

	return res;
    }
    return res;
}

function Relief2DTable_(img,shiftX,shiftY)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && typeof shiftX !== 'undefined' && shiftX !== null && typeof shiftY !== 'undefined' && shiftY !== null)
    {
        var i,j,ii,jj,startX = shiftX,startY = shiftY;

        for (i = startX,ii = 0;i < img.length;i++,ii++)
        {
	    res[ii] = [];
            for (j = shiftY,jj = 0;j < img[i].length;j++,jj++)
            {
		res[ii][jj] = 255 - img[i - shiftX][j - shiftY] + img[i][j];
            }
        }      

	return res;
    }
    return res;
}

function Relief2DTable(img,shiftX,shiftY)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0].length > 0 && typeof shiftX !== 'undefined' && shiftX !== null && typeof shiftY !== 'undefined' && shiftY !== null)
    {
        var i,j,ii,jj,startX = shiftX,startY = shiftY;

        for (i = startX,ii = 0;i < img.length;i++,ii++)
        {
	    res[ii] = [];
            for (j = shiftY,jj = 0;j < img[i].length;j++,jj++)
            {
		res[ii][jj] = Math.round((255 - img[i - shiftX][j - shiftY] + img[i][j])/2);
            }
        }      

	return res;
    }
    return res;
}

function Relief(img,shiftX,shiftY)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0 && typeof shiftX !== 'undefined' && shiftX !== null && typeof shiftY !== 'undefined' && shiftY !== null)
    {
	var R = GetR2DTable(img);
	var G = GetG2DTable(img);
	var B = GetB2DTable(img);

	R = Table2DToByte(Relief2DTable(R,shiftX,shiftY));
	G = Table2DToByte(Relief2DTable(G,shiftX,shiftY));
	B = Table2DToByte(Relief2DTable(B,shiftX,shiftY));

	res = MergeImageFrom2DTable(R,G,B);

	return res;
    }
    return res;
}

function Abs2DTable(tab)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
        var i,j;
        for (i = 0;i < tab.length;i++)
        {
            res[i] = [];
            for (j = 0;j < tab[i].length;j++)
            {
                res[i][j] = Math.abs(tab[i][j]);
            }
        }
        
    }
    return res;
}

function RobertsFilter2DTable(tab)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
        var i,j;
        for (i = 1;i < tab.length;i++)
        {
            res[i-1] = [];
            for (j = 1;j < tab[i].length;j++)
            {
                res[i-1][j-1] = Math.round((Math.abs(tab[i][j] - tab[i-1][j-1]) + Math.abs(tab[i][j-1] - tab[i-1][j]))/2);
            }
        }
        
    }
    return res;
}


function RobertsFilter(img)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0)
    {
	var R = GetR2DTable(img);
	var G = GetG2DTable(img);
	var B = GetB2DTable(img);

	R = Table2DToByte(RobertsFilter2DTable(R));
	G = Table2DToByte(RobertsFilter2DTable(G));
	B = Table2DToByte(RobertsFilter2DTable(B));

	res = MergeImageFrom2DTable(R,G,B);

	return res;
    }
    return res;
}


function Power2DTable(tab,p)
{
    if (p !== 'undefined' && p !== null && p >= 0 && tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var i,j,res = [];
	for(i = 0;i < tab.length;i++)
	{
	    res[i] = [];
	    for(j = 0;j < tab[i].length;j++)
	    {
		res[i][j] = Math.pow(tab[i][j],p);
	    }
	}
	return res;
    }
    return [];
}


function SobelFilter2DTable(tab)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
        var i,j,X,Y,A0,A1,A2,A3,A4,A5,A6,A7;
        for (i = 1;i < tab.length-1;i++)
        {
            res[i-1] = [];
            for (j = 1;j < tab[i].length - 1;j++)
            {
		A0 = tab[i-1][j-1];
		A1 = tab[i][j-1];
		A2 = tab[i + 1][j-1];
		A3 = tab[i + 1][j];
		A4 = tab[i + 1][j + 1];
		A5 = tab[i][j + 1];
		A6 = tab[i - 1][j + 1];
		A7 = tab[i - 1][j];
		X = (A2 + 2*A3 + A4) - (A0 + 2*A7 + A6);
		Y = (A0 + 2*A1 + A2) - (A6 + 2*A5 + A4);
                res[i-1][j-1] = Math.sqrt(X*X + Y*Y);
            }
        }
        
    }
    return res;
}


function SobelFilter(img,multi)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0 && multi !== 'undefined' && multi !== null && multi > 0)
    {
	var R = GetR2DTable(img);
	var G = GetG2DTable(img);
	var B = GetB2DTable(img);

	R = Table2DToByte(Multiple2DImage(SobelFilter2DTable(R),multi));
	G = Table2DToByte(Multiple2DImage(SobelFilter2DTable(G),multi));
	B = Table2DToByte(Multiple2DImage(SobelFilter2DTable(B),multi));

	res = MergeImageFrom2DTable(R,G,B);

	return res;
    }
    return res;
}

function KirschFilter2DTable(tab)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
        var i,j,k,A0,A1,A2,A3,A4,A5,A6,A7;
	var S = [],T = [],tmp = [];
        for (i = 1;i < tab.length-1;i++)
        {
            res[i-1] = [];
            for (j = 1;j < tab[i].length - 1;j++)
            {
		A0 = tab[i-1][j-1];
		A1 = tab[i][j-1];
		A2 = tab[i + 1][j-1];
		A3 = tab[i + 1][j];
		A4 = tab[i + 1][j + 1];
		A5 = tab[i][j + 1];
		A6 = tab[i - 1][j + 1];
		A7 = tab[i - 1][j];

		S[0] = A0 + A1 + A2;
		S[1] = A1 + A2 + A3;
		S[2] = A2 + A3 + A4;
		S[3] = A3 + A4 + A5;
		S[4] = A4 + A5 + A6;
		S[5] = A5 + A6 + A7;
		S[6] = A6 + A7 + A0;
		S[7] = A7 + A0 + A1;

		T[0] = A3 + A4 + A5 + A6 + A7;
		T[1] = A4 + A5 + A6 + A7 + A0;
		T[2] = A5 + A6 + A7 + A0 + A1;
		T[3] = A6 + A7 + A0 + A1 + A2;
		T[4] = A7 + A0 + A1 + A2 + A3;
		T[5] = A0 + A1 + A2 + A3 + A4;
		T[6] = A1 + A2 + A3 + A4 + A5;
		T[7] = A2 + A3 + A4 + A5 + A6;

		for(k = 0;k < 8;k++)
		    tmp[k] = Math.abs(5*S[k] - 3*T[k]);

                res[i-1][j-1] = Math.max(...tmp);
            }
        }
        
    }
    return res;
}


function KirschFilter(img,multi)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0 && multi !== 'undefined' && multi !== null && multi > 0)
    {
	var R = GetR2DTable(img);
	var G = GetG2DTable(img);
	var B = GetB2DTable(img);

	R = Table2DToByte(Multiple2DImage(KirschFilter2DTable(R),multi));
	G = Table2DToByte(Multiple2DImage(KirschFilter2DTable(G),multi));
	B = Table2DToByte(Multiple2DImage(KirschFilter2DTable(B),multi));

	res = MergeImageFrom2DTable(R,G,B);

	return res;
    }
    return res;
}

function VectorizationNearestNeighbor2DTable(tab,distance,treshold)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0 && distance !== 'undefined' && distance !== null && distance > 0 && treshold !== 'undefined' && treshold !== null && treshold > 0)
    {
        var i,ii,j,k;
	var YN;
	var x,y,x_,y_;


	var res1,res2,YN2 = true;
	for (ii = 0;YN2 == true;ii++)
	{
	    YN2 = false;
	    YN = false;
	    k = 0;

	    res[ii] = [];
	    res[ii][0] = [];
	    res[ii][1] = [];

	    res1 = [];
	    res1[0] = [];
	    res1[0][0] = [];
	    res1[0][1] = [];

	    res2 = [];
	    res2[0] = [];
	    res2[0][0] = [];
	    res2[0][1] = [];


	    for (i = 0;i < tab.length;i++)
	    {
		for (j = 0;j < tab[i].length;j++)
		{
		    if (tab[i][j] > treshold)
		    {
			res1[0][1][k] = i;
			res1[0][0][k] = j;
			res2[0][1][k] = i;
			res2[0][0][k] = j;
			tab[i][j] = 0
			YN = true;
			YN2 = true;
			k = k + 1;
			break;
		    }
		}
		if (YN === true)
		    break;
	    }
	    if (YN === true)
	    {
		
		for (;YN == true;)
		{
		    YN = false;
		    x = res1[0][1][k-1];
		    y = res1[0][0][k-1];
		    for (j = 1;j <= distance;j++)
		    {
			for (i = -j;i <=j;i++)
			{
			    x_ = x + i;
			    y_ = y - j;
			    if (x_ >= 0 && y_ >= 0 && x_ < tab.length && y_ < tab[x_].length && tab[x_][y_] > treshold)
				YN = true;
			    else
			    {
				x_ = x + i;
				y_ = y + j;
				if (x_ >= 0 && y_ >= 0 && x_ < tab.length && y_ < tab[x_].length && tab[x_][y_] > treshold)
				    YN = true;
				else{
				    x_ = x - j;
				    y_ = y + i;
				    if (x_ >= 0 && y_ >= 0 && x_ < tab.length && y_ < tab[x_].length && tab[x_][y_] > treshold)
					YN = true;
				    else{
					x_ = x + j;
					y_ = y + i;
					if (x_ >= 0 && y_ >= 0 && x_ < tab.length && y_ < tab[x_].length && tab[x_][y_] > treshold)
					    YN = true;
				    }
				}
			    }

			    if (YN === true)
			    {
				res1[0][1][k] = x_;
				res1[0][0][k] = y_;
				tab[x_][y_] = 0
				k = k + 1;
				break;
			    }
			}
			if (YN === true)
			    break;
		    }
		}
		YN = true;
		k = 1;
		for (;YN == true;)
		{
		    YN = false;
		    x = res2[0][1][k-1];
		    y = res2[0][0][k-1];
		    for (j = 1;j <= distance;j++)
		    {
			for (i = -j;i <=j;i++)
			{
			    x_ = x + i;
			    y_ = y - j;
			    if (x_ >= 0 && y_ >= 0 && x_ < tab.length && y_ < tab[x_].length && tab[x_][y_] > treshold)
				YN = true;
			    else
			    {
				x_ = x + i;
				y_ = y + j;
				if (x_ >= 0 && y_ >= 0 && x_ < tab.length && y_ < tab[x_].length && tab[x_][y_] > treshold)
				    YN = true;
				else{
				    x_ = x - j;
				    y_ = y + i;
				    if (x_ >= 0 && y_ >= 0 && x_ < tab.length && y_ < tab[x_].length && tab[x_][y_] > treshold)
					YN = true;
				    else{
					x_ = x + j;
					y_ = y + i;
					if (x_ >= 0 && y_ >= 0 && x_ < tab.length && y_ < tab[x_].length && tab[x_][y_] > treshold)
					    YN = true;
				    }
				}
			    }

			    if (YN === true)
			    {
				res2[0][1][k] = x_;
				res2[0][0][k] = y_;
				tab[x_][y_] = 0
				k = k + 1;
				break;
			    }
			}
			if (YN === true)
			    break;
		    }
		}
		k = 0;
		if (res2[0][1].length > 0)
		{
		    for(i = res2[0][1].length-1;i >= 0;i--,k++)
		    {
			res[ii][1][k] = res2[0][1][i];
			res[ii][0][k] = res2[0][0][i];
		    }
		}
		if (res1[0][1].length > 1)
		{
		    for(i = 0;i < res1[0][1].length;i++,k++)
		    {
			res[ii][1][k] = res1[0][1][i];
			res[ii][0][k] = res1[0][0][i];
		    }
		}
	    }
	}        
    }
    return res;
}

function VectorizationNearestNeighbor(img,distance,treshold)
{
    var res = [];
    if (typeof img !== 'undefined' && img !== null && img.length > 0 && img[0].length > 0 && img[0][0].length > 0 && distance !== 'undefined' && distance !== null && distance > 0 && treshold !== 'undefined' && treshold !== null && treshold > 0)
    {
	var obr = GetR2DTable(img);

	res = VectorizationNearestNeighbor2DTable(obr,distance,treshold);

	return res;
    }
    return res;
}

function DetectionLine2DTable(tab,nAlpha,minP,maxP,stepP,treshold)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0 && nAlpha !== 'undefined' && nAlpha !== null && nAlpha > 0  && maxP !== 'undefined' && maxP !== null  && minP !== 'undefined' && minP !== null && stepP > 0 && stepP !== 'undefined' && stepP > 0 && treshold !== 'undefined' && treshold !== null && treshold > 0)
    {
	var i,ii,j,jj,x,y,alpha_,p_,nP = (maxP - minP)/stepP;
	var stepAlphaRad = Math.PI/nAlpha;
	var res_ = [];
	res_[0] = [];
	res_[1] = [];
	res_[2] = [];

	for(i = 0;i < nP;i++)
	{
	    res[i] = [];
	    for(j = 0;j < nAlpha;j++)
	    {
		res[i][j] = 0;
	    }
	}

	for(i = 0;i < tab.length;i++)
	{
	    for(j = 0;j < tab[0].length;j++)
	    {
		if (tab[i][j] >= treshold)
		{
		    x = j;
		    y = i;
		    for (alpha_ = 0,ii = 0;alpha_ < Math.PI;alpha_ += stepAlphaRad,ii++)
		    {
			p_ = x*Math.cos(alpha_) + y*Math.sin(alpha_);
			jj = Math.round((p_ - minP)/stepP);
//			if (res.length <= jj)
//			    res[jj] = [];
			if (jj >= 0 && ii >= 0 && jj < nP && ii < nAlpha)
			    res[jj][ii] = res[jj][ii] + 1;
		    }
		}
	    }
	}
    }
    return res;
}


function DetectionLineGray(tab,nAlpha,minP,maxP,stepP,treshold,multi)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0 && nAlpha !== 'undefined' && nAlpha !== null && nAlpha > 0 && maxP > 0 && maxP !== 'undefined' && maxP > 0 && stepP > 0 && stepP !== 'undefined' && stepP > 0 && treshold !== 'undefined' && treshold !== null && treshold > 0 && multi !== 'undefined' && multi !== null && multi > 0 && minP !== 'undefined' && minP !== null )
    {
	var R = GetR2DTable(tab);

	R = Table2DToByte(Multiple2DImage(DetectionLine2DTable(R,nAlpha,minP,maxP,stepP,treshold),multi));

	res = MergeImageFrom2DTable(R,R,R);

	return res;
    }
    return res;
}

function MirrorWidth2DTable(tab)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var i,j;

	for(i = 0;i < tab.length;i++)
	{
	    res[i] = [];
	    for(j = 0;j < tab[0].length;j++)
	    {
		res[i][j] = tab[i][tab[0].length - j - 1];
	    }
	}
    }
    return res;
}

function MirrorHeight2DTable(tab)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var i,j;

	for(i = 0;i < tab.length;i++)
	{
	    res[i] = [];
	}

	for(i = 0;i < tab.length;i++)
	{
	    for(j = 0;j < tab[0].length;j++)
	    {
		res[i][j] = tab[tab.length - i - 1][j];
	    }
	}

    }
    return res;
}

function DetectionCircle2DTable(tab,r,stepAlpha,treshold)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0 && stepAlpha !== 'undefined' && stepAlpha !== null && stepAlpha > 0 && r !== 'undefined' && r !== null && r > 0  && treshold !== 'undefined' && treshold !== null && treshold > 0)
    {
	var stepAlphaRad = stepAlpha*Math.PI/180;
	var i,j,x,y,alpha_,x0,y0;

	for(i = 0;i < tab.length;i++)
	{
	    res[i] = [];
	    for(j = 0;j < tab[0].length;j++)
	    {
		res[i][j] = 0;
	    }
	}

	for(i = 0;i < tab.length;i++)
	{
	    for(j = 0;j < tab[0].length;j++)
	    {
		if (tab[i][j] >= treshold)
		{
		    x = j;
		    y = i;
		    for (alpha_ = 0;alpha_ < 2*Math.PI;alpha_ += stepAlphaRad)
		    {
			x0 = Math.round(x - r*Math.cos(alpha_));
			y0 = Math.round(y - r*Math.sin(alpha_));

			if (x0 >= 0 && y0 >= 0 && x0 < tab[0].length && y0 < tab.length)
			    res[y0][x0] = res[y0][x0] + 1;
		    }
		}
	    }
	}
    }
    return res;
}

function DetectionCircleGray(tab,r,stepAlpha,treshold,multi)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0 && r !== 'undefined' && r !== null && r > 0 && stepAlpha > 0 && stepAlpha !== 'undefined' && stepAlpha > 0 && treshold !== 'undefined' && treshold !== null && treshold > 0 && multi !== 'undefined' && multi !== null && multi > 0 )
    {
	var R = GetR2DTable(tab);

	R = Table2DToByte(Multiple2DImage(DetectionCircle2DTable(R,r,stepAlpha,treshold),multi));

	res = MergeImageFrom2DTable(R,R,R);

	return res;
    }
    return res;
}

function ColorSeparationdAlphaBeta(tab)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var R = GetR2DTable(tab);
	var G = GetG2DTable(tab);
	var B = GetB2DTable(tab);

	if (typeof R !== 'undefined' && R !== null && R.length > 0 && R[0].length > 0 && typeof G !== 'undefined' && G !== null && G.length > 0 && G[0].length > 0 && typeof B !== 'undefined' && B !== null && B.length > 0 && B[0].length > 0)
	{

	    var i,j,r_,g_,b_,tmp2;
	    var d = [],alpha = [],beta = []; 

	    for(i = 0;i < R.length;i++)
	    {
		d[i] = []; 
		alpha[i] = []; 
		beta[i] = []; 
		for(j = 0;j < R[0].length;j++)
		{
		    r_ = R[i][j]/255;
		    g_ = G[i][j]/255;
		    b_ = B[i][j]/255;
		    d[i][j] = Math.sqrt(r_*r_ + g_*g_ + b_*b_);
		    if (r_ == 0 && g_ == 0 && b_ == 0)
			alpha[i][j] = 0;
		    else
			alpha[i][j] = Math.acos((r_ + g_ + b_)/Math.sqrt(3*(r_*r_ + g_*g_ + b_*b_)))*180/Math.PI;
//		    tmp = b_ - g_;
		    if ((r_ + b_ + g_)/3 == r_)
		    {
			beta[i][j] = 180;
		    }else
		    {
			tmp2 = Math.sqrt(3)*(b_-g_)/(2*Math.sqrt(b_*b_ + g_*g_ + r_*r_ - b_*g_ - b_*r_ - g_*r_));
			if (RoundValue(tmp2,3) == -1)
			{
			    beta[i][j] = 180;
			}else
			{
			    tmp2 = Math.acos(tmp2)*180/Math.PI;
			    if ((r_ + b_ + g_)/3 >= r_)
			    {
				beta[i][j] = tmp2;
			    }else
				beta[i][j] = 360-tmp2;
			}
		    }
		}
	    }
	}

	res = MergeImageFrom2DTable(d,alpha,beta);

	return res;
    }
    return res;
}

function dAlphaBetaToRGB(tab)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var d = GetR2DTable(tab);
	var alpha = GetG2DTable(tab);
	var beta = GetB2DTable(tab);

	if (typeof d !== 'undefined' && d !== null && d.length > 0 && d[0].length > 0 && typeof alpha !== 'undefined' && alpha !== null && alpha.length > 0 && alpha[0].length > 0 && typeof beta !== 'undefined' && beta !== null && beta.length > 0 && beta[0].length > 0)
	{

	    var i,j,d_,alpha_,beta_,tmp,tmp2;
	    var R = [],G = [],B = []; 

	    for(i = 0;i < d.length;i++)
	    {
		R[i] = []; 
		G[i] = []; 
		B[i] = []; 
		for(j = 0;j < d[0].length;j++)
		{
		    d_ = d[i][j];
		    alpha_ = alpha[i][j];
		    beta_ = beta[i][j];

		    R[i][j] = -Math.sqrt(6)*d_*Math.sin(alpha_*Math.PI/180)*Math.sin(beta_*Math.PI/180)/3 + d_*Math.cos(alpha_*Math.PI/180)/Math.sqrt(3);
		    G[i][j] = -d_*Math.sin(alpha_*Math.PI/180)*Math.cos(beta_*Math.PI/180)/Math.sqrt(2) + d_*Math.sin(alpha_*Math.PI/180)*Math.sin(beta_*Math.PI/180)/Math.sqrt(6) + d_*Math.cos(alpha_*Math.PI/180)/Math.sqrt(3);
		    B[i][j] = d_*Math.sin(alpha_*Math.PI/180)*Math.cos(beta_*Math.PI/180)/Math.sqrt(2) + d_*Math.sin(alpha_*Math.PI/180)*Math.sin(beta_*Math.PI/180)/Math.sqrt(6) + d_*Math.cos(alpha_*Math.PI/180)/Math.sqrt(3);
		    R[i][j] = R[i][j]*255;
		    G[i][j] = G[i][j]*255;
		    B[i][j] = B[i][j]*255;

		}
	    }
	}

	res = MergeImageFrom2DTable(R,G,B);

	return res;
    }
    return res;
}

function dAlphaBetaManipulation(tab,d,alpha,beta)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0 && typeof d !== 'undefined' && d !== null && typeof alpha !== 'undefined' && alpha !== null && typeof beta !== 'undefined' && beta !== null)
    {
	var tab2 = ColorSeparationdAlphaBeta(tab);
	if (typeof tab2 !== 'undefined' && tab2 !== null && tab.length > 0 && tab2[0].length > 0)
	{
	    var d_ = GetR2DTable(tab2);
	    var alpha_ = GetG2DTable(tab2);
	    var beta_ = GetB2DTable(tab2);

	    if (typeof d_ !== 'undefined' && d_ !== null && d_.length > 0 && d_[0].length > 0 && typeof alpha_ !== 'undefined' && alpha_ !== null && alpha_.length > 0 && alpha_[0].length > 0 && typeof beta_ !== 'undefined' && beta_ !== null && beta_.length > 0 && beta_[0].length > 0)
	    {

		var i,j;

		for(i = 0;i < d_.length;i++)
		{
		    for(j = 0;j < d_[0].length;j++)
		    {
			d_[i][j] = d_[i][j]*d;
			alpha_[i][j] = alpha_[i][j]*alpha;
			beta_[i][j] = beta_[i][j] + beta;
		    }

		}
		var tab3 = MergeImageFrom2DTable(d_,alpha_,beta_);
		res = dAlphaBetaToRGB(tab3);
	    }
	    
	}
    }
    return res;
}

function ColorSeparationdR(tab)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var R = GetR2DTable(tab);
	return MergeImageFrom2DTable(R,R,R);
    }
}

function ColorSeparationdG(tab)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var G = GetG2DTable(tab);
	return MergeImageFrom2DTable(G,G,G);
    }
}

function ColorSeparationdB(tab)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var B = GetB2DTable(tab);
	return MergeImageFrom2DTable(B,B,B);
    }
}

function Table2DAverageVector(tab)
{
    if (tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var i,j,res = [];
	var av = MeanTable2D(tab);
	for(i = 0;i < tab.length;i++)
	{
	    res[i] = [];
	    for(j = 0;j < tab[i].length;j++)
	    {
		res[i][j] = av;

	    }
	}
	return res;
    }
    return [];
}

function Table2DVariabilityVector(tab)
{
    if (tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var i,j,res = [];
	var av = MeanTable2D(tab);
	for(i = 0;i < tab.length;i++)
	{
	    res[i] = [];
	    for(j = 0;j < tab[i].length;j++)
	    {
		res[i][j] = tab[i][j] - av;

	    }
	}
	return res;
    }
    return [];
}

function Table2DChangeBrightnessContrast(tab,b,c)
{
    if (typeof b !== 'undefined' && b !== null && typeof c !== 'undefined' && c !== null && tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var i,j,res = [];
	var aav = Table2DAverageVector(tab);
	var av = Table2DVariabilityVector(tab);
	for(i = 0;i < tab.length;i++)
	{
	    res[i] = [];
	    for(j = 0;j < tab[i].length;j++)
	    {
		res[i][j] = aav[i][j]*b + av[i][j]*c;

	    }
	}
	return res;
    }
    return [];
}


function ChangeBrightnessContrast(tab,b,c)
{
    var res = [];
    if (typeof b !== 'undefined' && b !== null && typeof c !== 'undefined' && c !== null && typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
	var R = GetR2DTable(tab);
	var G = GetG2DTable(tab);
	var B = GetB2DTable(tab);

	R = Table2DChangeBrightnessContrast(R,b,c);
	G = Table2DChangeBrightnessContrast(G,b,c);
	B = Table2DChangeBrightnessContrast(B,b,c);

	res = MergeImageFrom2DTable(R,G,B);
    }
    return res;
}

function VectorComponentRGB(tab,r,g,b)
{
    var res = [];
    if (typeof r !== 'undefined' && r !== null && typeof g !== 'undefined' && g !== null && typeof b !== 'undefined' && b !== null && typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
		var R_ = GetR2DTable(tab);
		var G_ = GetG2DTable(tab);
		var B_ = GetB2DTable(tab);
		var i,j;
		if (typeof R_ !== 'undefined' && R_ !== null && R_.length > 0 && R_[0].length > 0 && typeof G_ !== 'undefined' && G_ !== null && G_.length > 0 && G_[0].length > 0 && typeof B_ !== 'undefined' && B_ !== null && B_.length > 0 && B_[0].length > 0)
		{
			var i,denominator = r*r + g*g + b*b;

			for(i = 0;i < R_.length;i++)
			{
				res[i] = [];
				for(j = 0;j < R_[i].length;j++)
				{
					
					res[i][j] = (R_[i][j]*r + G_[i][j]*g + B_[i][j]*b)/denominator;

				}
			}
		}
    }
    return res; 	
}

function CalculateAW(tab,r,g,b)
{
    var res = [];
    if (typeof r !== 'undefined' && r !== null && typeof g !== 'undefined' && g !== null && typeof b !== 'undefined' && b !== null && typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
		var R_ = GetR2DTable(tab);
		var G_ = GetG2DTable(tab);
		var B_ = GetB2DTable(tab);
		var c = VectorComponentRGB(tab,r,g,b);
		var i;
		if (typeof R_ !== 'undefined' && R_ !== null && R_.length > 0 && R_[0].length > 0 && typeof G_ !== 'undefined' && G_ !== null && G_.length > 0 && G_[0].length > 0 && typeof B_ !== 'undefined' && B_ !== null && B_.length > 0 && B_[0].length > 0 && typeof c !== 'undefined' && c !== null && c.length > 0 && c[0].length > 0)
		{
			var i,j;

			for(i = 0;i < c.length;i++)
			{
				for(j = 0;j < c[i].length;j++)
				{
					R_[i][j] = r*c[i][j];
					G_[i][j] = g*c[i][j];
					B_[i][j] = b*c[i][j];
				}
			}
		}
		res = MergeImageFrom2DTable(R_,G_,B_);
		
    }
    return res; 	
}

function PhotoFilter(tab,r,g,b,w)
{
    var res = [];
    if (typeof w !== 'undefined' && w !== null && typeof r !== 'undefined' && r !== null && typeof g !== 'undefined' && g !== null && typeof b !== 'undefined' && b !== null && typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
    {
		var R_ = GetR2DTable(tab);
		var G_ = GetG2DTable(tab);
		var B_ = GetB2DTable(tab);
		var c = VectorComponentRGB(tab,r,g,b);
		var i;
		if (typeof R_ !== 'undefined' && R_ !== null && R_.length > 0 && R_[0].length > 0 && typeof G_ !== 'undefined' && G_ !== null && G_.length > 0 && G_[0].length > 0 && typeof B_ !== 'undefined' && B_ !== null && B_.length > 0 && B_[0].length > 0 && typeof c !== 'undefined' && c !== null && c.length > 0 && c[0].length > 0)
		{
			var i,j;

			for(i = 0;i < c.length;i++)
			{
				for(j = 0;j < c[i].length;j++)
				{
					R_[i][j] = (1-w)*R_[i][j] + w*r*c[i][j];
					G_[i][j] = (1-w)*G_[i][j] + w*g*c[i][j];
					B_[i][j] = (1-w)*B_[i][j] + w*b*c[i][j];
				}
			}
		}
		res = MergeImageFrom2DTable(R_,G_,B_);
		
    }
    return res; 	
}

function DetMatrix3x3(x1,x2,x3)
{
    var res = [];
    if (typeof x1 !== 'undefined' && x1 !== null && x1.length == 3 && typeof x2 !== 'undefined' && x2 !== null && x2.length == 3 && typeof x3 !== 'undefined' && x3 !== null && x3.length == 3)
    {
			var a11 = x1[0]*x1[0] + x1[1]*x1[1] + x1[2]*x1[2];
			var a12 = x1[0]*x2[0] + x1[1]*x2[1] + x1[2]*x2[2];
			var a13 = x1[0]*x3[0] + x1[1]*x3[1] + x1[2]*x3[2];
			var a21 = a12;
			var a22 = x2[0]*x2[0] + x2[1]*x2[1] + x2[2]*x2[2];
			var a23 = x2[0]*x3[0] + x2[1]*x3[1] + x2[2]*x3[2];
			var a31 = a13;
			var a32 = a23;
			var a33 = x3[0]*x3[0] + x3[1]*x3[1] + x3[2]*x3[2];
			var res = a11*a22*a33 + a21*a32*a13 + a31*a12*a23 - a21*a12*a33 - a11*a32*a23 - a31*a22*a13;
			return res;
		
    }
    return res; 	
}

function c1RGBColor(a,x1,x2,x3)
{
    var res = [];
    if (typeof a !== 'undefined' && a !== null && a.length == 3 && typeof x1 !== 'undefined' && x1 !== null && x1.length == 3 && typeof x2 !== 'undefined' && x2 !== null && x2.length == 3 && typeof x3 !== 'undefined' && x3 !== null && x3.length == 3)
    {
			var d = DetMatrix3x3(x1,x2,x3);
			var a1 = a[0]*x1[0] + a[1]*x1[1] + a[2]*x1[2];
			var a2 = a[0]*x2[0] + a[1]*x2[1] + a[2]*x2[2];
			var a3 = a[0]*x3[0] + a[1]*x3[1] + a[2]*x3[2];
			var a11 = x1[0]*x1[0] + x1[1]*x1[1] + x1[2]*x1[2];
			var a12 = x1[0]*x2[0] + x1[1]*x2[1] + x1[2]*x2[2];
			var a13 = x1[0]*x3[0] + x1[1]*x3[1] + x1[2]*x3[2];
			var a21 = a12;
			var a22 = x2[0]*x2[0] + x2[1]*x2[1] + x2[2]*x2[2];
			var a23 = x2[0]*x3[0] + x2[1]*x3[1] + x2[2]*x3[2];
			var a31 = a13;
			var a32 = a23;
			var a33 = x3[0]*x3[0] + x3[1]*x3[1] + x3[2]*x3[2];
			var res = a1*a22*a33 + a2*a32*a13 + a3*a12*a23 - a2*a12*a33 - a1*a32*a23 - a3*a22*a13;
			return res/d;
		
    }
    return res; 	
}

function c2RGBColor(a,x1,x2,x3)
{
    var res = [];
    if (typeof a !== 'undefined' && a !== null && a.length == 3 && typeof x1 !== 'undefined' && x1 !== null && x1.length == 3 && typeof x2 !== 'undefined' && x2 !== null && x2.length == 3 && typeof x3 !== 'undefined' && x3 !== null && x3.length == 3)
    {
			var d = DetMatrix3x3(x1,x2,x3);
			var a1 = a[0]*x1[0] + a[1]*x1[1] + a[2]*x1[2];
			var a2 = a[0]*x2[0] + a[1]*x2[1] + a[2]*x2[2];
			var a3 = a[0]*x3[0] + a[1]*x3[1] + a[2]*x3[2];
			var a11 = x1[0]*x1[0] + x1[1]*x1[1] + x1[2]*x1[2];
			var a12 = x1[0]*x2[0] + x1[1]*x2[1] + x1[2]*x2[2];
			var a13 = x1[0]*x3[0] + x1[1]*x3[1] + x1[2]*x3[2];
			var a21 = a12;
			var a22 = x2[0]*x2[0] + x2[1]*x2[1] + x2[2]*x2[2];
			var a23 = x2[0]*x3[0] + x2[1]*x3[1] + x2[2]*x3[2];
			var a31 = a13;
			var a32 = a23;
			var a33 = x3[0]*x3[0] + x3[1]*x3[1] + x3[2]*x3[2];
			var res = a11*a2*a33 + a21*a3*a13 + a31*a1*a23 - a21*a1*a33 - a11*a3*a23 - a31*a2*a13;
			return res/d;
		
    }
    return res; 	
}

function c3RGBColor(a,x1,x2,x3)
{
    var res = [];
    if (typeof a !== 'undefined' && a !== null && a.length == 3 && typeof x1 !== 'undefined' && x1 !== null && x1.length == 3 && typeof x2 !== 'undefined' && x2 !== null && x2.length == 3 && typeof x3 !== 'undefined' && x3 !== null && x3.length == 3)
    {
			var d = DetMatrix3x3(x1,x2,x3);
			var a1 = a[0]*x1[0] + a[1]*x1[1] + a[2]*x1[2];
			var a2 = a[0]*x2[0] + a[1]*x2[1] + a[2]*x2[2];
			var a3 = a[0]*x3[0] + a[1]*x3[1] + a[2]*x3[2];
			var a11 = x1[0]*x1[0] + x1[1]*x1[1] + x1[2]*x1[2];
			var a12 = x1[0]*x2[0] + x1[1]*x2[1] + x1[2]*x2[2];
			var a13 = x1[0]*x3[0] + x1[1]*x3[1] + x1[2]*x3[2];
			var a21 = a12;
			var a22 = x2[0]*x2[0] + x2[1]*x2[1] + x2[2]*x2[2];
			var a23 = x2[0]*x3[0] + x2[1]*x3[1] + x2[2]*x3[2];
			var a31 = a13;
			var a32 = a23;
			var a33 = x3[0]*x3[0] + x3[1]*x3[1] + x3[2]*x3[2];
			var res = a11*a22*a3 + a21*a32*a1 + a31*a12*a2 - a21*a12*a3 - a11*a32*a2 - a31*a22*a1;
			return res/d;
		
    }
    return res; 	
}

function c1RGBColorTable(tab,x1,x2,x3)
{
    var res = [];
    if (typeof x1 !== 'undefined' && x1 !== null && x1.length == 3 && typeof x2 !== 'undefined' && x2 !== null && x2.length == 3 && typeof x3 !== 'undefined' && x3 !== null && x3.length == 3 && typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
	{
		var R_ = GetR2DTable(tab);
		var G_ = GetG2DTable(tab);
		var B_ = GetB2DTable(tab);
		if (typeof R_ !== 'undefined' && R_ !== null && R_.length > 0 && R_[0].length > 0 && typeof G_ !== 'undefined' && G_ !== null && G_.length > 0 && G_[0].length > 0 && typeof B_ !== 'undefined' && B_ !== null && B_.length > 0 && B_[0].length > 0)
		{
			var i,j,a = [];

			for(i = 0;i < R_.length;i++)
			{
				res[i] = [];
				for(j = 0;j < R_[i].length;j++)
				{
					a[0] = R_[i][j];
					a[1] = G_[i][j];
					a[2] = B_[i][j];
					res[i][j] = c1RGBColor(a,x1,x2,x3);
				}
			}
		}		
	}
    return res; 	
}

function c2RGBColorTable(tab,x1,x2,x3)
{
    var res = [];
    if (typeof x1 !== 'undefined' && x1 !== null && x1.length == 3 && typeof x2 !== 'undefined' && x2 !== null && x2.length == 3 && typeof x3 !== 'undefined' && x3 !== null && x3.length == 3 && typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
	{
		var R_ = GetR2DTable(tab);
		var G_ = GetG2DTable(tab);
		var B_ = GetB2DTable(tab);
		if (typeof R_ !== 'undefined' && R_ !== null && R_.length > 0 && R_[0].length > 0 && typeof G_ !== 'undefined' && G_ !== null && G_.length > 0 && G_[0].length > 0 && typeof B_ !== 'undefined' && B_ !== null && B_.length > 0 && B_[0].length > 0)
		{
			var i,j,a = [];

			for(i = 0;i < R_.length;i++)
			{
				res[i] = [];
				for(j = 0;j < R_[i].length;j++)
				{
					a[0] = R_[i][j];
					a[1] = G_[i][j];
					a[2] = B_[i][j];
					res[i][j] = c2RGBColor(a,x1,x2,x3);
				}
			}
		}		
	}
    return res; 	
}

function c3RGBColorTable(tab,x1,x2,x3)
{
    var res = [];
    if (typeof x1 !== 'undefined' && x1 !== null && x1.length == 3 && typeof x2 !== 'undefined' && x2 !== null && x2.length == 3 && typeof x3 !== 'undefined' && x3 !== null && x3.length == 3 && typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0)
	{
		var R_ = GetR2DTable(tab);
		var G_ = GetG2DTable(tab);
		var B_ = GetB2DTable(tab);
		if (typeof R_ !== 'undefined' && R_ !== null && R_.length > 0 && R_[0].length > 0 && typeof G_ !== 'undefined' && G_ !== null && G_.length > 0 && G_[0].length > 0 && typeof B_ !== 'undefined' && B_ !== null && B_.length > 0 && B_[0].length > 0)
		{
			var i,j,a = [];

			for(i = 0;i < R_.length;i++)
			{
				res[i] = [];
				for(j = 0;j < R_[i].length;j++)
				{
					a[0] = R_[i][j];
					a[1] = G_[i][j];
					a[2] = B_[i][j];
					res[i][j] = c3RGBColor(a,x1,x2,x3);
				}
			}
		}		
	}
    return res; 	
}

function ColorCorrection(tab,x1,x2,x3,m1,m2,m3)
{
    var res = [];
    if (typeof x1 !== 'undefined' && x1 !== null && x1.length == 3 && typeof x2 !== 'undefined' && x2 !== null && x2.length == 3 && typeof x3 !== 'undefined' && x3 !== null && x3.length == 3 && typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0 && typeof m1 !== 'undefined' && m1 !== null && typeof m2 !== 'undefined' && m2 !== null && typeof m3 !== 'undefined' && m3 !== null)
	{
		var X1_ = c1RGBColorTable(tab,x1,x2,x3);
		var X2_ = c2RGBColorTable(tab,x1,x2,x3);
		var X3_ = c3RGBColorTable(tab,x1,x2,x3);

		if (typeof X1_ !== 'undefined' && X1_ !== null && X1_.length > 0 && X1_[0].length > 0 && typeof X2_ !== 'undefined' && X2_ !== null && X2_.length > 0 && X2_[0].length > 0 && typeof X3_ !== 'undefined' && X3_ !== null && X3_.length > 0 && X3_[0].length > 0)
		{
			var R_ = []; 
			var G_ = []; 
			var B_ = []; 
			var i,j = [];
			
			for(i = 0;i < X1_.length;i++)
			{
				R_[i] = []; 
				G_[i] = []; 
				B_[i] = []; 
				for(j = 0;j < X1_[i].length;j++)
				{
					R_[i][j] = m1*X1_[i][j]*x1[0] + m2*X2_[i][j]*x2[0] + m3*X3_[i][j]*x3[0];
					G_[i][j] = m1*X1_[i][j]*x1[1] + m2*X2_[i][j]*x2[1] + m3*X3_[i][j]*x3[1];
					B_[i][j] = m1*X1_[i][j]*x1[2] + m2*X2_[i][j]*x2[2] + m3*X3_[i][j]*x3[2];
				}
			}
			res = MergeImageFrom2DTable(R_,G_,B_);
		}
	}
    return res; 	
}


function FunctionAxisX(min_,max_,step){
    var res = [],i,j;
    for (i = 0,j = min_;j <= max_;i++,j+=step)
    	res[i] = j;
    
    return res;
}

function FunctionSinAxisY(min_,max_,step,n,fi,shiftY){
    var res = [],i,j;
	var tab = FunctionAxisX(min_,max_,step);
    for (i = 0;i < tab.length;i++)
    	res[i] = Math.sin((tab[i])*n + fi) + shiftY;
    
    return res;
}

function FunctionASinAxisY(min_,max_,step,n,fi,shiftY,ampliude){
    var res = [],i,j;
	var tab = FunctionAxisX(min_,max_,step);
    for (i = 0;i < tab.length;i++)
    	res[i] = ampliude*Math.sin((tab[i])*n + fi) + shiftY;
    
    return res;
}

function FunctionOnes(min_,max_,step,shiftY){
    var res = [],i,j;
	var tab = FunctionAxisX(min_,max_,step);
    for (i = 0;i < tab.length;i++)
    	res[i] = shiftY;
    
    return res;
}

function FunctionShift(tab,shift){
    var res = [],i,j;
    for (i = 0;i < tab.length;i++)
	{
		j = i + shift;
		if (j >= tab.length)
			j = j - tab.length
		if (j >= tab.length)
			j = j - tab.length
    	res[j] = tab[i];
    }
	
    return res;
}


function FunctionMerge(tab1,tab2){
    var res = [],i,j;
    for (i = 0;i < tab1.length;i++)
    	res[i] = tab1[i];
    for (j = 0;j < tab2.length;i++,j++)
    	res[i] = tab2[j];
    
    return res;
}

function FunctionSinCosAxisY(min_,max_,step,nSin,nCos,ampliudeSin,ampliudeCos,fiSin,fiCos,shiftY){
    var res = [],i,j;
	var sin_ = FunctionSinAxisY(min_,max_,step,nSin,fiSin,0);
	var cos_ = FunctionSinAxisY(min_,max_,step,nCos,fiCos + Math.PI/2,0);
	
    for (i = 0;i < sin_.length;i++)
    	res[i] = sin_[i]*ampliudeSin + cos_[i]*ampliudeCos + shiftY;
    
    return res;
}

function FunctionRectangularSignal(y,divider){
	
	var tmp = Math.floor(y);
	tmp = tmp%divider;
	if (tmp > 0)
		tmp = 1;
    return 0.5-tmp;
}

function FunctionRectangularSignalY(min_,max_,step,nPeriods,ampliude,fi,shiftY,divider){
    var res = [],i,j;
	var tab = FunctionAxisX(min_,max_,step);
    for (i = 0;i < tab.length;i++)
    	res[i] = ampliude*FunctionRectangularSignal(((tab[i])*nPeriods*(divider))/2 + fi,divider) + shiftY;
    
    return res;
}

function FunctionRandSignalY(min_,max_,step,ampliude){
    var res = [],i,j;
	var tab = FunctionAxisX(min_,max_,step);
    for (i = 0;i < tab.length;i++)
    	res[i] = ampliude*Math.random();
    
    return res;
}

function SumSignal(tab1,tab2){
    var res = [],i,j,n;
	if (tab1.length < tab2.length)
		n = tab1.length;
	else
		n = tab2.length;
		
    for (i = 0;i < n;i++)
	{
		res[i] = tab1[i] + tab2[i];
	}
    return res;
}


function FunctionFFTLowPassFilterMask(min_,max_,step,f0,f,mean){
    var res = [],i,j,ind,ind2;
	var tab = FunctionAxisX(min_,max_,step);

	var tab2 = [];

    for (i = 0;i < tab.length;i++)
		tab2[i] = f0*i;

	ind = -1;
	
    for (i = 0;i < tab2.length;i++)
		if (tab2[i] >= f)
		{
			ind = i+3;
			break;
		}
	
	ind2 = tab.length - ind + 1;
	var res2 = [];	
    for (i = 0;i < tab.length;i++)
	{
		if (i <= ind || i >= ind2)
			res[i] = 1;
		else
			res[i] = 0;
		res2[i] = res[i];
	}
	
    for (i = 0;i < res.length;i++)
	{
		if (i-4 < 0)
			a1 = 1;
		else 
			a1 = res[i-4];
		if (i-3 < 0)
			a2 = 1;
		else 
			a2 = res[i-3];
		if (i-2 < 0)
			a3 = 1;
		else 
			a3 = res[i-2];
		if (i-1 < 0)
			a4 = 1;
		else 
			a4 = res[i-1];

		a5 = res[i];

		if (i+1 >= res.length)
			a6 = 1;
		else 
			a6 = res[i+1];
		if (i+2 >= res.length)
			a7 = 1;
		else 
			a7 = res[i+2];
		if (i+3 >= res.length)
			a8 = 1;
		else 
			a8 = res[i+3];
		if (i+4 >= res.length)
			a9 = 1;
		else 
			a9 = res[i+4];
		
		res2[i] = 0.025*a1 + 0.05*a2 + 0.125*a3 + 0.175*a4 + 0.25*a5 + 0.175*a6 + 0.125*a7 + 0.05*a8 + 0.025*a9
	}
	
    return res2;
}


function FunctionFFTHighPassFilterMask(min_,max_,step,f0,f,mean){
    var res = [],i,j,ind,ind2;
	var tab = FunctionAxisX(min_,max_,step);

	var tab2 = [];

    for (i = 0;i < tab.length;i++)
		tab2[i] = f0*i;

	ind = -1;
	
    for (i = 0;i < tab2.length;i++)
		if (tab2[i] >= f)
		{
			ind = i-5;
			break;
		}
	
	ind2 = tab.length - ind + 1;
	var res2 = [];	
    for (i = 0;i < tab.length;i++)
	{
		if (i <= ind || i >= ind2)
			res[i] = 0;
		else
			res[i] = 1;
		res2[i] = res[i];
	}
	
    for (i = 0;i < res.length;i++)
	{
		if (i-4 < 0)
			a1 = 0;
		else 
			a1 = res[i-4];
		if (i-3 < 0)
			a2 = 0;
		else 
			a2 = res[i-3];
		if (i-2 < 0)
			a3 = 0;
		else 
			a3 = res[i-2];
		if (i-1 < 0)
			a4 = 0;
		else 
			a4 = res[i-1];

		a5 = res[i];

		if (i+1 >= res.length)
			a6 = 0;
		else 
			a6 = res[i+1];
		if (i+2 >= res.length)
			a7 = 0;
		else 
			a7 = res[i+2];
		if (i+3 >= res.length)
			a8 = 0;
		else 
			a8 = res[i+3];
		if (i+4 >= res.length)
			a9 = 0;
		else 
			a9 = res[i+4];
		
		res2[i] = 0.025*a1 + 0.05*a2 + 0.125*a3 + 0.175*a4 + 0.25*a5 + 0.175*a6 + 0.125*a7 + 0.05*a8 + 0.025*a9
	}
	
    return res2;
}


function FunctionFFTBandPassFilterMask(min_,max_,step,f0,f,B,mean){
    var res = [],i,j,ind,indB0,indB1,ind2,indB0_2,indB1_2,YNB0;
	var tab = FunctionAxisX(min_,max_,step);

	var tab2 = [];

    for (i = 0;i < tab.length;i++)
		tab2[i] = f0*i;

	ind = -1;
    for (i = 0;i < tab2.length;i++)
		if (tab2[i] >= f)
		{
			ind = i;
			break;
		}
	if (ind < 0)
		return res;
	
	YNB0 = 0;
	indB0 = -1;
    for (i = 0;i < tab2.length;i++)
		if (tab2[i] >= f-B/2)
		{
			indB0 = i-5;
			break;
		}
	if (indB0 < 0)
	{
		indB0 = 0;
		YNB0 = 1;
	}
	
	indB1 = -1;
    for (i = 0;i < tab2.length;i++)
		if (tab2[i] >= f+B/2)
		{
			indB1 = i+5;
			break;
		}
	if (indB1 < 0)
		return res;
	
	ind2 = tab.length - ind + 1;
	indB0_2 = tab.length - indB0 + 1;
	indB1_2 = tab.length - indB1 + 1;
	var res2 = [];	
    for (i = 0;i < tab.length;i++)
	{
		if ((i >= indB0 && i <= indB1) || (i >= indB1_2 && i <= indB0_2))
			res[i] = 1;
		else
			res[i] = 0;
		res2[i] = res[i];
	}
	
	var a1,a2,a3,a4,a5,a6,a7,a8,a9;
	
    for (i = 0;i < res.length;i++)
	{
		if (i-4 < 0)
			a1 = YNB0;
		else 
			a1 = res[i-4];
		if (i-3 < 0)
			a2 = YNB0;
		else 
			a2 = res[i-3];
		if (i-2 < 0)
			a3 = YNB0;
		else 
			a3 = res[i-2];
		if (i-1 < 0)
			a4 = YNB0;
		else 
			a4 = res[i-1];

		a5 = res[i];

		if (i+1 >= res.length)
			a6 = YNB0;
		else 
			a6 = res[i+1];
		if (i+2 >= res.length)
			a7 = YNB0;
		else 
			a7 = res[i+2];
		if (i+3 >= res.length)
			a8 = YNB0;
		else 
			a8 = res[i+3];
		if (i+4 >= res.length)
			a9 = YNB0;
		else 
			a9 = res[i+4];
		
		res2[i] = 0.025*a1 + 0.05*a2 + 0.125*a3 + 0.175*a4 + 0.25*a5 + 0.175*a6 + 0.125*a7 + 0.05*a8 + 0.025*a9
	}
	
    return res2;
}

function FunctionFFTBandStopFilterMask(min_,max_,step,f0,f,B,mean){
    var res = [],i,j,ind,indB0,indB1,ind2,indB0_2,indB1_2,YNB0;
	var tab = FunctionAxisX(min_,max_,step);

	var tab2 = [];

    for (i = 0;i < tab.length;i++)
		tab2[i] = f0*i;

	ind = -1;
    for (i = 0;i < tab2.length;i++)
		if (tab2[i] >= f)
		{
			ind = i;
			break;
		}
	if (ind < 0)
		return res;
	
	YNB0 = 1;
	indB0 = -1;
    for (i = 0;i < tab2.length;i++)
		if (tab2[i] >= f-B/2)
		{
			indB0 = i-5;
			break;
		}
	if (indB0 < 0)
	{
		indB0 = 0;
		YNB0 = 0;
	}
	
	indB1 = -1;
    for (i = 0;i < tab2.length;i++)
		if (tab2[i] >= f+B/2)
		{
			indB1 = i+5;
			break;
		}
	if (indB1 < 0)
		return res;
	
	ind2 = tab.length - ind + 1;
	indB0_2 = tab.length - indB0 + 1;
	indB1_2 = tab.length - indB1 + 1;
	var res2 = [];	
    for (i = 0;i < tab.length;i++)
	{
		if ((i >= indB0 && i <= indB1) || (i >= indB1_2 && i <= indB0_2))
			res[i] = 0;
		else
			res[i] = 1;
		res2[i] = res[i];
	}
	
	var a1,a2,a3,a4,a5,a6,a7,a8,a9;
	
    for (i = 0;i < res.length;i++)
	{
		if (i-4 < 0)
			a1 = YNB0;
		else 
			a1 = res[i-4];
		if (i-3 < 0)
			a2 = YNB0;
		else 
			a2 = res[i-3];
		if (i-2 < 0)
			a3 = YNB0;
		else 
			a3 = res[i-2];
		if (i-1 < 0)
			a4 = YNB0;
		else 
			a4 = res[i-1];

		a5 = res[i];

		if (i+1 >= res.length)
			a6 = YNB0;
		else 
			a6 = res[i+1];
		if (i+2 >= res.length)
			a7 = YNB0;
		else 
			a7 = res[i+2];
		if (i+3 >= res.length)
			a8 = YNB0;
		else 
			a8 = res[i+3];
		if (i+4 >= res.length)
			a9 = YNB0;
		else 
			a9 = res[i+4];
		
		res2[i] = 0.025*a1 + 0.05*a2 + 0.125*a3 + 0.175*a4 + 0.25*a5 + 0.175*a6 + 0.125*a7 + 0.05*a8 + 0.025*a9
	}
	
    return res2;
}


function MultipleMaskFFT(mask,tabFFT){
    var res = [],i,j,n;
	if (mask.length < tabFFT[0].length)
		n = mask.length;
	else
		n = tabFFT[0].length;
	
	res[0] = [];res[1] = [];
	
    for (i = 0;i < n;i++)
	{
		res[0][i] = mask[i]*tabFFT[0][i];
		res[1][i] = mask[i]*tabFFT[1][i];
	}
    return res;
}

function FunctionRe(tab){
    var res = [],i,j;
	
    for (i = 0;i < tab[0].length;i++)
    	res[i] = tab[0][i];
    
    return res;
}

function FunctionIm(tab){
    var res = [],i,j;
	
    for (i = 0;i < tab[1].length;i++)
    	res[i] = tab[1][i];
    
    return res;
}

function FunctionAbs(tab){
    var res = [],i,j;
	
    for (i = 0;i < tab[1].length;i++)
    	res[i] = Math.sqrt(tab[0][i]*tab[0][i] + tab[1][i]*tab[1][i]);
    
    return res;
}

function FunctionAlpha(tab){
    var res = [],i,j;
	
    for (i = 0;i < tab[1].length;i++)
    	res[i] = Math.atan2(tab[1][i],tab[0][i]);
    
    return res;
}

function FunctionOpposite(tab){
    var res = [],i,j;
	res[0] = [];
	res[1] = [];	
	
    for (i = 0;i < tab[1].length;i++)
	{
    	res[0][i] = tab[0][i]/(tab[0][i]*tab[0][i] + tab[1][i]*tab[1][i]);
    	res[1][i] = -tab[1][i]/(tab[0][i]*tab[0][i] + tab[1][i]*tab[1][i]);
	}
    
    return res;
}

function FunctionAlphaDegrees(tab){
    var res = [],i,j;
	
    for (i = 0;i < tab[1].length;i++)
    	res[i] = Math.atan2(tab[1][i],tab[0][i])*180/Math.PI;
    
    return res;
}

function FunctionFFT(tab){
    var res = [],i,j;
	res[0] = [];
	res[1] = [];
	
	
	M = tab.length;
	for (j = 0;j < tab.length;j++)
	{
		res[0][j] = 0;
		res[1][j] = 0;
		for (i = 0;i < tab.length;i++)
		{
			res[0][j] = res[0][j] + tab[i]*Math.cos(-2*Math.PI*i*j/M);
			res[1][j] = res[1][j] + tab[i]*Math.sin(-2*Math.PI*i*j/M);
		}		
		res[0][j] = res[0][j]/M;
		res[1][j] = res[1][j]/M;
	}
    return res;
}

function FunctionFFTv2(tab){
    var res = [],i,j;
	res[0] = [];
	res[1] = [];
	
	
	M = tab.length;
	for (j = 0;j < tab.length;j++)
	{
		res[0][j] = 0;
		res[1][j] = 0;
		for (i = 0;i < tab.length;i++)
		{
			res[0][j] = res[0][j] + tab[i]*Math.cos(-2*Math.PI*i*j/M);
			res[1][j] = res[1][j] + tab[i]*Math.sin(-2*Math.PI*i*j/M);
		}		
	}
    return res;
}

function FunctionIFFT(tab){
    var res = [],i,j;
	res[0] = [];
	res[1] = [];
	
	
	M = tab[0].length;
	for (j = 0;j < tab[0].length;j++)
	{
		res[0][j] = 0;
		res[1][j] = 0;
		for (i = 0;i < tab[0].length;i++)
		{
			res[0][j] = res[0][j] + tab[0][i]*Math.cos(2*Math.PI*i*j/M) - tab[1][i]*Math.sin(2*Math.PI*i*j/M);
			res[1][j] = res[1][j] + tab[0][i]*Math.sin(2*Math.PI*i*j/M) + tab[1][i]*Math.cos(2*Math.PI*i*j/M);
		}		
	}
    return res;
}

function FunctionIFFTv2(tab){
    var res = [],i,j;
	res[0] = [];
	res[1] = [];
	
	
	M = tab[0].length;
	for (j = 0;j < tab[0].length;j++)
	{
		res[0][j] = 0;
		res[1][j] = 0;
		for (i = 0;i < tab[0].length;i++)
		{
			res[0][j] = res[0][j] + tab[0][i]*Math.cos(2*Math.PI*i*j/M) - tab[1][i]*Math.sin(2*Math.PI*i*j/M);
			res[1][j] = res[1][j] + tab[0][i]*Math.sin(2*Math.PI*i*j/M) + tab[1][i]*Math.cos(2*Math.PI*i*j/M);
		}		
		res[0][j] = res[0][j]/M;
		res[1][j] = res[1][j]/M;
	}
    return res;
}

function FunctionTrigonometricSeriesA(tab){
    var res = [],i,j,n,M;
	
	n = tab.length;
	res[0] = 0;
	for (i = 0;i < tab.length;i++)
	{
		res[0] = res[0] + tab[i]*Math.cos(2*Math.PI*i*0/n);
	}		
	res[0] = res[0]/n;
	
	if (n%2 == 0)
		M = n/2;
	else
		M = (n-1)/2;
	for (j = 1;j <= M;j++)
	{
		res[j] = 0;
		for (i = 0;i < tab.length;i++)
		{
			res[j] = res[j] + tab[i]*Math.cos(2*Math.PI*i*j/n);
		}		
		res[j] = 2*res[j]/n;
	}
    return res;
}

function FunctionTrigonometricSeriesB(tab){
    var res = [],i,j,n,M;
	
	n = tab.length;
	
	if (n%2 == 0)
		M = n/2 - 1;
	else
		M = (n-1)/2;
	for (j = 1;j <= M;j++)
	{
		res[j-1] = 0;
		for (i = 0;i < tab.length;i++)
		{
			res[j-1] = res[j-1] + tab[i]*Math.sin(2*Math.PI*i*j/n);
		}		
		res[j-1] = 2*res[j-1]/n;
	}
    return res;
}


function FunctionDCT(tab){
    var res = [],i,j;
	
	
	M = tab.length;
	for (j = 0;j < tab.length;j++)
	{
		res[j] = 0;
		for (i = 0;i < tab.length;i++)
		{
			res[j] = res[j] + tab[i]*Math.cos(Math.PI*(2*i + 1)*j/(2*M));
		}		
		res[j] = 2*res[j]/M;
	}
    return res;
}

function ColorHSV2RGB(HSV){
    var res = [];
	
    if (typeof HSV !== 'undefined' && HSV !== null && HSV.length == 3)
	{
		var C,H_,X,m;
		
		C = HSV[1]*HSV[2];

		H_ = HSV[0]/60;

		X = C*(1-Math.abs(H_%2 - 1));

		res[0] = 0;res[1] = 0;res[2] = 0;
		if (H_ >= 0 && H_ <= 1)
		{
			res[0] = C;res[1] = X;res[2] = 0;
		}else
		{
			if (H_ > 1 && H_ <= 2)
			{
				res[0] = X;res[1] = C;res[2] = 0;
			}else
			{
				if (H_ > 2 && H_ <= 3)
				{
					res[0] = 0;res[1] = C;res[2] = X;
				}else
				{
					if (H_ > 3 && H_ <= 4)
					{
						res[0] = 0;res[1] = X;res[2] = C;
					}else
					{
						if (H_ > 4 && H_ <= 5)
						{
							res[0] = X;res[1] = 0;res[2] = C;
						}else
						{
							if (H_ > 5 && H_ <= 6)
							{
								res[0] = C;res[1] = 0;res[2] = X;
							}else
							{
								res[0] = 0;res[1] = 0;res[2] = 0;								
							}												
						}											
					}					
				}
			}
		}
		
		m = HSV[2]-C;
		res[0] = 255*(res[0] + m);
		res[1] = 255*(res[1] + m);
		res[2] = 255*(res[2] + m);
	}
    return res;
}

function ColorRGB2HSV(RGB){
    var res = [];
	
    if (typeof RGB !== 'undefined' && RGB !== null && RGB.length == 3)
	{
		var R,G,B,max_,min_,H,S,V,C;
		
		R = RGB[0]/255;
		G = RGB[1]/255;
		B = RGB[2]/255;
		
		max_ = R;
		if (max_ < G)
			max_ = G;
		if (max_ < B)
			max_ = B;

		min_ = R;
		if (min_ > G)
			min_ = G;
		if (min_ > B)
			min_ = B;
			
		V = max_;
		C = max_ - min_;
		
		if (C == 0)
			H = 0;
		else
		{
			if (V == R)
			{
				H = 60*(0 + (G-B)/C);
			}else
			{
				if (V == G)
				{
					H = 60*(2 + (B-R)/C);
				}else
				{
					if (V == B)
					{
						H = 60*(4 + (R-G)/C);
					}else
					{
						H = 0;
					}
				}
			}
		}
		
		if (V == 0)
			S = 0;
		else
			S = C/V;
		
		if (H < 0)
			H = H + 360;
		
		res[0] = H;
		res[1] = S;
		res[2] = V;
	}
    return res;
}


function ColorRGB24bitOut(RGB){
    var res = [];
	
    if (typeof RGB !== 'undefined' && RGB !== null && RGB.length == 3)
	{
		res = [[[256*256*Math.round(RGB[0]) +256*Math.round(RGB[1]) + Math.round(RGB[2])]]];
	}
    return res;
}

function RGBSumcolors(RGB1,RGB2){
    var res = [];
	
    if (typeof RGB1 !== 'undefined' && RGB1 !== null && RGB1.length == 3 && typeof RGB2 !== 'undefined' && RGB2 !== null && RGB2.length == 3)
	{		
		res = [RGB1[0] + RGB2[0],RGB1[1] + RGB2[1],RGB1[2] + RGB2[2]];
		var max_ = res[0];
		if (res[1] > max_)
			max_ = res[1];
		if (res[2] > max_)
			max_ = res[2];
		if (max_ > 255)
		{
			res[0] = res[0]*255/max_;
			res[1] = res[1]*255/max_;
			res[2] = res[2]*255/max_;
		}
	}
    return res;
}


function RGBWhiteComponent(RGB){
    var res = [];
	
    if (typeof RGB !== 'undefined' && RGB !== null && RGB.length == 3)
	{
		var min_ = RGB[0];
		if (RGB[1] < min_)
			min_ = RGB[1];
		if (RGB[2] < min_)
			min_ = RGB[2];
		
		res = [min_,min_,min_];
	}
    return res;
}

function RGBColorComponent(RGB){
    var res = [];
	
    if (typeof RGB !== 'undefined' && RGB !== null && RGB.length == 3)
	{
		var min_ = RGB[0];
		if (RGB[1] < min_)
			min_ = RGB[1];
		if (RGB[2] < min_)
			min_ = RGB[2];
		
		res = [RGB[0] - min_,RGB[1] - min_,RGB[2] - min_];
	}
    return res;
}

function Table1DElement(tab,no){
    var res = [];
	
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && typeof no !== 'undefined' && no !== null && tab.length > no && no >= 0)
	{
		return tab[no];
	}
    return res;
}

function CycliShift2DTableX(tab,v)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && tab[0].length > 0 && typeof v !== 'undefined' && v !== null)
    {
	var i,j;

	for(i = 0;i < tab.length;i++)
	{
	    res[i] = [];
	    for(j = 0;j < tab[0].length;j++)
	    {
		res[i][j] = tab[i][(j + v)%tab[0].length];
	    }
	}
    }
    return res;
}

function RoundTable1DValue(tab,v)
{
    var res = [];
    if (typeof tab !== 'undefined' && tab !== null && tab.length > 0 && typeof v !== 'undefined' && v !== null)
    {
	var i,j;

	for(i = 0;i < tab.length;i++)
	{
	    res[i] = RoundValue(tab[i],v);
	}
    }
    return res;
}

function Multiple1DTable(img0,img1)
{
    var res = [];
	res[0] = [];
	res[1] = [];

    if (typeof img0 !== 'undefined' && img0 !== null && img0.length > 0 && img0[0].length > 0 && img0[0].length > 0 && typeof img1 !== 'undefined' && img1 !== null && img1.length > 0 && img1[0].length > 0 && img1[0].length > 0 && img0.length == img1.length && img0[0].length == img1[0].length)
    {
        var i;
        for (i = 0;i < img0[0].length;i++)
        {
		res[0][i] = img0[0][i]*img1[0][i] - img0[1][i]*img1[1][i];
		res[1][i] = img0[0][i]*img1[1][i] + img0[1][i]*img1[0][i];
	} 

    }
    return res;
}

function Exp1DTable(img0,v)
{
    var res = [],A,alpha;
	res[0] = [];
	res[1] = [];

    if (typeof img0 !== 'undefined' && img0 !== null && img0.length > 0 && img0[0].length > 0 && img0[0].length > 0 && typeof v !== 'undefined' && v !== null)
    {
        var i;
        for (i = 0;i < img0[0].length;i++)
        {
			A = Math.sqrt(img0[0][i]*img0[0][i] + img0[1][i]*img0[1][i]);
			alpha = Math.atan2(img0[1][i],img0[0][i]);
			A = Math.pow(A,v);
			alpha = v*alpha;
		res[0][i] = A*Math.cos(alpha);
		res[1][i] = A*Math.sin(alpha);
	} 

    }
    return res;
}

function Exp1DTableAlpha(img0,v)
{
    var res = [],A,alpha;

    if (typeof img0 !== 'undefined' && img0 !== null && img0.length > 0 && img0[0].length > 0 && img0[0].length > 0 && typeof v !== 'undefined' && v !== null)
    {
        var i;
        for (i = 0;i < img0[0].length;i++)
        {
			A = Math.sqrt(img0[0][i]*img0[0][i] + img0[1][i]*img0[1][i]);
			alpha = Math.atan2(img0[1][i],img0[0][i]);
			A = Math.pow(A,v);
			alpha = v*alpha;
		res[i] = alpha*180/Math.PI;
	} 

    }
    return res;
}

function randn_bm() {
    var u = 0, v = 0;
    while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
    while(v === 0) v = Math.random();
    return Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
}

function FunctionRandTab(mean,sigma,n){
    var res = [],i,j;
    for (i = 0;i < n;i++)
    	res[i] = mean + sigma*randn_bm();
    
    return res;
}


function Rotate2D(tab,angle){
    var res = [],i,j;
	res[0] = [];res[1] = [];
	var m00 = Math.cos(angle),m01 = Math.sin(angle);
	var m10 = -m01,m11 = m00;
    for (i = 0;i < tab[0].length;i++)
	{
		res[0][i] = tab[0][i]*m00 + tab[1][i]*m01;
		res[1][i] = tab[0][i]*m10 + tab[1][i]*m11;
	}
    
    return res;
}

function MultipleByValue1DTable(tab,v)
{
    var res = [],i;
    for (i = 0;i < tab.length;i++)
    	res[i] = tab[i]*v;
    
    return res;	
}

function AddValue1DTable(tab,v)
{
    var res = [],i;
    for (i = 0;i < tab.length;i++)
    	res[i] = tab[i] + v;
    
    return res;	
}

function Covariance2D(tab)
{
    var i;
	
	var m0 = MeanTable(tab[0]);
	var m1 = MeanTable(tab[1]);
	
	var s = 0;
    for (i = 0;i < tab[0].length;i++)
    	s = s + (tab[0][i] - m0)*(tab[1][i] - m1);
    
    return s/tab[0].length;	
}

function VarianceTable(tab)
{
    var i;
	
	var m = MeanTable(tab);

	var s = 0;
    for (i = 0;i < tab.length;i++)
    	s = s + (tab[i] - m)*(tab[i] - m);

    return s/tab.length;	
}

function VarianceTable2D(tab,no)
{
    var i;
	
	var m = MeanTable(tab[no]);

	var s = 0;
    for (i = 0;i < tab[no].length;i++)
    	s = s + (tab[no][i] - m)*(tab[no][i] - m);

    return s/tab[no].length;	
}

function CalculateCov(sigmaAx,sigmaAy,covA,sigmaBx,sigmaBy,covB)
{
	if (covA == 0 && covB == 0)
		return 0;
	else
	{
		if (covA != 0)
		{
			return (1 + sigmaBx/sigmaAx)*(1 + sigmaBy/sigmaAy)*covA;
		}else
			return (1 + sigmaAx/sigmaBx)*(1 + sigmaAy/sigmaBy)*covB;
	}
}

function MultiSign(value,sign)
{
	if (sign >= 0)
		return value;
	else
		return -value;
}