/// <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);
        }
Пример #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);
        }
Пример #3
0
        private void OptionGeneratePalette_Click(object sender, RoutedEventArgs e)
        {
            bitmapArray = new FastBitmapArray((int)DrawingScrollView.ViewportWidth, (int)DrawingScrollView.ViewportHeight);

            bitmapArrayWithoutLines = null;

            bitmapArray.SetBatchArea(0, 0, bitmapArray.Width - 1, bitmapArray.Height - 1);

            double xJump    = 1.0 / bitmapArray.Width;
            int    ySegment = bitmapArray.Height / (1 + 3 + 3 + 3 + 3);

            //double xJump = 1.0 / bitmapArray.Width;

            for (int x = 0; x < bitmapArray.Width; ++x)
            {
                int y    = 0;
                int yMax = ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                    //bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    //bitmapArray.SetRedBatch(x, y, x * xJump);
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                    //bitmapArray.SetGreenBatch(x, y, x * xJump);
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                    bitmapArray.SetGreenBatch(x, y, 1);
                    bitmapArray.SetBlueBatch(x, y, 1);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, 1);
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                    bitmapArray.SetBlueBatch(x, y, 1);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, 1);
                    bitmapArray.SetGreenBatch(x, y, 1);
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                    bitmapArray.SetBlueBatch(x, y, 1);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, 1);
                    bitmapArray.SetGreenBatch(x, y, x * xJump);
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }

                yMax += ySegment;
                for (; y < yMax; ++y)
                {
                    bitmapArray.SetRedBatch(x, y, x * xJump);
                    bitmapArray.SetGreenBatch(x, y, 1);
                    bitmapArray.SetBlueBatch(x, y, x * xJump);
                }
            }

            DrawingImage.Source = bitmapArray.GetBitmap(Mask.Disabled);
            DrawingImage.Width  = bitmapArray.Width;
            DrawingImage.Height = bitmapArray.Height;
            ReinitializeMask();

            if (latestFileName != null)
            {
                latestFileName = null;

                OptionReload.IsEnabled = false;
            }
        }