예제 #1
0
        private void FilterWithCorrection(FastBitmapArray /*bitmap*/ array, int x, int y)
        {
            double red   = array.GetRed(x, y);
            double green = array.GetGreen(x, y);
            double blue  = array.GetBlue(x, y);

            double redNew   = FilterRed(red, green, blue);
            double greenNew = FilterGreen(red, green, blue);
            double blueNew  = FilterBlue(red, green, blue);

            if (redNew < 0)
            {
                redNew = 0;
            }
            else if (redNew > 1)
            {
                redNew = 1;
            }
            if (greenNew < 0)
            {
                greenNew = 0;
            }
            else if (greenNew > 1)
            {
                greenNew = 1;
            }
            if (blueNew < 0)
            {
                blueNew = 0;
            }
            else if (blueNew > 1)
            {
                blueNew = 1;
            }

            array.SetPixelBatch(x, y, redNew, greenNew, blueNew);
        }
예제 #2
0
        public FastBitmapArray Process(FastBitmapArray array, ErrorDiffusionKernelName kernelName, int levelsCount)
        {
            if (levelsCount < 2)
            {
                throw new ArgumentException("at least 2 levels are needed");
            }

            var processed = new FastBitmapArray(array.Width, array.Height);

            int levelsCountLess = levelsCount - 1;

            double[] levels = new double[levelsCount];
            // upper bounds for all levels (except for the last level, cos this one is always 1.0)
            double[] levelsBounds = new double[levelsCountLess];
            for (int i = 0; i < levelsCount; ++i)
            {
                levels[i] = ((double)i) / levelsCountLess;
                if (i > 0)
                {
                    levelsBounds[i - 1] = (levels[i - 1] + levels[i]) / 2;
                }
            }

            var matrix        = Matrices[kernelName];
            var matrixSum     = MatricesSums[kernelName];
            var matrixWidth   = matrix[0].Length;
            var matrixHeight  = matrix.Length;
            var currentPixelX = (matrixWidth - 1) / 2;

            for (int y = 0; y < array.Height; ++y)
            {
                for (int x = 0; x < array.Width; ++x)
                {
                    // get color value
                    double red   = array.GetRed(x, y);
                    double green = array.GetGreen(x, y);
                    double blue  = array.GetBlue(x, y);

                    // add error accumulated from previous pixels
                    red   += processed.GetRed(x, y);
                    green += processed.GetGreen(x, y);
                    blue  += processed.GetBlue(x, y);

                    // approximate
                    double redApprox = levels[levelsCountLess];
                    for (int i = 0; i < levelsCountLess; ++i)
                    {
                        if (red < levelsBounds[i])
                        {
                            redApprox = levels[i];
                            break;
                        }
                    }
                    double greenApprox = levels[levelsCountLess];
                    for (int i = 0; i < levelsCountLess; ++i)
                    {
                        if (green < levelsBounds[i])
                        {
                            greenApprox = levels[i];
                            break;
                        }
                    }
                    double blueApprox = levels[levelsCountLess];
                    for (int i = 0; i < levelsCountLess; ++i)
                    {
                        if (blue < levelsBounds[i])
                        {
                            blueApprox = levels[i];
                            break;
                        }
                    }

                    // calculate error
                    double redError   = red - redApprox;
                    double greenError = green - greenApprox;
                    double blueError  = blue - blueApprox;

                    // set current pixel value
                    processed.SetRedBatch(x, y, redApprox);
                    processed.SetGreenBatch(x, y, greenApprox);
                    processed.SetBlueBatch(x, y, blueApprox);

                    // diffuse the arror accross other pixels
                    for (int xx = 0; xx < matrixWidth; ++xx)
                    {
                        for (int yy = 0; yy < matrixHeight; ++yy)
                        {
                            if (yy == 0 && xx <= currentPixelX)
                            {
                                continue;
                            }

                            int xxx = x + xx - currentPixelX;
                            int yyy = y + yy;

                            if (xxx < 0 || xxx >= array.Width || yyy >= array.Height)
                            {
                                continue;
                            }

                            double level = ((double)matrix[yy][xx]) / matrixSum;
                            processed.SetRedBatch(xxx, yyy,
                                                  processed.GetRed(xxx, yyy) + redError * level);
                            processed.SetGreenBatch(xxx, yyy,
                                                    processed.GetGreen(xxx, yyy) + greenError * level);
                            processed.SetBlueBatch(xxx, yyy,
                                                   processed.GetBlue(xxx, yyy) + blueError * level);
                        }
                    }
                }
            }

            processed.SetBatchArea();

            return(processed);
        }
        /// <summary>
        /// Processes the input array.
        /// </summary>
        /// <param name="array"></param>
        /// <param name="matrixSize"></param>
        /// <returns></returns>
        public FastBitmapArray Process(FastBitmapArray array, int matrixSize, int levelsCount)
        {
            #region old approach
            //var processed = new FastBitmapArray(array.Width * matrixSize, array.Height * matrixSize);

            //int procXmin = 0;
            //int procXmax = 0;
            //int procYmin = 0;
            //int procYmax = 0;

            //var matrix = Matrices[matrixSize];
            //var matrixCoef = matrixSize * matrixSize + 1;

            //for (int x = 0; x < array.Width; ++x)
            //{
            //	procXmin = x * matrixSize;
            //	procXmax = procXmin + matrixSize;
            //	for (int y = 0; y < array.Height; ++y)
            //	{
            //		double red = array.GetRed(x, y);
            //		double green = array.GetGreen(x, y);
            //		double blue = array.GetBlue(x, y);

            //		procYmin = y * matrixSize;
            //		procYmax = procYmin + matrixSize;
            //		for (int xx = procXmin, xxx = 0; xx < procXmax; ++xx, ++xxx)
            //			for (int yy = procYmin, yyy = 0; yy < procYmax; ++yy, ++yyy)
            //			{
            //				double matrixValue = ((double)matrix[xxx][yyy]) / matrixCoef;
            //				processed.SetRed(xx, yy, red > matrixValue ? 1 : 0);
            //				processed.SetGreen(xx, yy, green > matrixValue ? 1 : 0);
            //				processed.SetBlue(xx, yy, blue > matrixValue ? 1 : 0);
            //			}
            //	}
            //}
            #endregion

            // new approach:
            var processed = new FastBitmapArray(array.Width, array.Height);

            int levelsCountLess = levelsCount - 1;

            var    matrix      = Matrices[matrixSize];
            var    matrixCoef  = matrixSize * matrixSize + 1;
            double matrixLevel = 1.0 / levelsCountLess;

            double[] levels = new double[levelsCount];
            // upper bounds for all levels (except for the last level, cos this one is always 1.0)
            double[] levelsBounds = new double[levelsCountLess];
            for (int i = 0; i < levelsCount; ++i)
            {
                levels[i] = ((double)i) / levelsCountLess;
                if (i > 0)
                {
                    levelsBounds[i - 1] = (levels[i - 1] + levels[i]) / 2;
                }
                if (i > 0 && i < levelsCount - 1)
                {
                    levels[i] += 0.5 / (levelsCountLess * (matrixCoef - 1) + 1);
                }
            }

            int matrixX = 0;
            int matrixY = 0;

            for (int x = 0; x < array.Width; ++x)
            {
                for (int y = 0; y < array.Height; ++y)
                {
                    double matrixValue = matrixLevel * ((double)matrix[matrixY][matrixX]) / matrixCoef;

                    double red   = array.GetRed(x, y);
                    double green = array.GetGreen(x, y);
                    double blue  = array.GetBlue(x, y);

                    // approximation
                    double redApprox   = processOnePixel(red, levels, levelsBounds, levelsCountLess, matrixValue);
                    double greenApprox = processOnePixel(green, levels, levelsBounds, levelsCountLess, matrixValue);
                    double blueApprox  = processOnePixel(blue, levels, levelsBounds, levelsCountLess, matrixValue);

                    processed.SetRedBatch(x, y, redApprox);
                    processed.SetGreenBatch(x, y, greenApprox);
                    processed.SetBlueBatch(x, y, blueApprox);

                    ++matrixY;
                    if (matrixY == matrixSize)
                    {
                        matrixY = 0;
                    }
                }
                ++matrixX;
                if (matrixX == matrixSize)
                {
                    matrixX = 0;
                }
            }

            processed.SetBatchArea();

            return(processed);
        }