示例#1
0
        public static RasterColor FindClosestColor(
            RasterColor color,
            RasterColor[] palette,
            ColorDifferencingMethod colorDifferencingMethod)
        {
            double minDistance = double.MaxValue;
            var    bestIndex   = 0;

            switch (colorDifferencingMethod)
            {
            case ColorDifferencingMethod.EuclideanDistance:
                for (var i = 0; i < palette.Length; i++)
                {
                    double distance = color.CalculateEuclideanDistance(palette[i]);
                    if (!(distance < minDistance))
                    {
                        continue;
                    }
                    minDistance = distance;
                    bestIndex   = i;
                }
                break;

            case ColorDifferencingMethod.RelativeLuminance601:
                for (var i = 0; i < palette.Length; i++)
                {
                    double distance = color.CalculateRelativeLuminance601(palette[i]);
                    if (!(distance < minDistance))
                    {
                        continue;
                    }
                    minDistance = distance;
                    bestIndex   = i;
                }
                break;

            case ColorDifferencingMethod.RelativeLuminance709:
                for (var i = 0; i < palette.Length; i++)
                {
                    double distance = color.CalculateRelativeLuminance709(palette[i]);
                    if (!(distance < minDistance))
                    {
                        continue;
                    }
                    minDistance = distance;
                    bestIndex   = i;
                }
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(colorDifferencingMethod), colorDifferencingMethod, null);
            }

            return(palette[bestIndex]);
        }
示例#2
0
        public static RasterImage NoDithering(RasterImage image, RasterColor[] ditheringPalette,
                                              ColorDifferencingMethod colorMatching)
        {
            int width = image.Width, height = image.Height;
            int rOffset, bOffset, gOffset;

            if (image.Order == RasterByteOrder.Bgr)
            {
                rOffset = 2;
                gOffset = 1;
                bOffset = 0;
            }
            else
            {
                rOffset = 0;
                gOffset = 1;
                bOffset = 2;
            }

            byte[] buffer = AllocateImageBytes(image);

            // Translates the x,y coordinates to a buffer index
            int CalculateIndex(int x, int y)
            {
                return(y * width * (image.BitsPerPixel == 24 ? 3 : 4)
                       + x * (image.BitsPerPixel == 24 ? 3 : 4));
            }

            for (var y = 0; y < height; y++)
            {
                for (var x = 0; x < width; x++)
                {
                    int index = CalculateIndex(x, y);

                    byte b = buffer[index + bOffset];
                    byte r = buffer[index + rOffset];
                    byte g = buffer[index + gOffset];

                    RasterColor bestColor = FindClosestColor(new RasterColor(r, g, b), ditheringPalette, colorMatching);

                    buffer[index + bOffset] = bestColor.B;
                    buffer[index + rOffset] = bestColor.R;
                    buffer[index + gOffset] = bestColor.G;
                }
            }
            SetImageBytes(image, buffer);

            return(image);
        }
示例#3
0
        public static RasterImage ErrorDiffusionDithering(ErrorDiffusionMatrix matrix, RasterImage image,
                                                          RasterColor[] ditheringPalette,
                                                          ColorDifferencingMethod colorMatching)
        {
            int width = image.Width,
                height = image.Height;
            int rOffset, bOffset, gOffset;

            if (image.Order == RasterByteOrder.Bgr)
            {
                rOffset = 2;
                gOffset = 1;
                bOffset = 0;
            }
            else
            {
                rOffset = 0;
                gOffset = 1;
                bOffset = 2;
            }

            byte[] buffer = AllocateImageBytes(image);

            int CalculateIndex(int x, int y)
            {
                return(y * width * (image.BitsPerPixel == 24 ? 3 : 4) + x * (image.BitsPerPixel == 24 ? 3 : 4));
            }

            int CalculateError(int error, int numerator, int denominator)
            {
                if (error == 0)
                {
                    return(0);
                }
                // fixes problem where for example -5/8==0, but -5>>3 == -1.
                return((int)Math.Floor((double)error * numerator / denominator));
            }

            void ApplyError(int bx, int by, int[] error, int numerator, int denominator)
            {
                int currentIndex = CalculateIndex(bx, by);

                buffer[currentIndex + bOffset] = AddClamp(buffer[currentIndex + bOffset],
                                                          CalculateError(error[bOffset], numerator, denominator));
                buffer[currentIndex + gOffset] = AddClamp(buffer[currentIndex + gOffset],
                                                          CalculateError(error[gOffset], numerator, denominator));
                buffer[currentIndex + rOffset] = AddClamp(buffer[currentIndex + rOffset],
                                                          CalculateError(error[rOffset], numerator, denominator));
            }

            for (var y = 0; y < height; y++)
            {
                for (var x = 0; x < width; x++)
                {
                    int index = CalculateIndex(x, y);

                    byte b = buffer[index + bOffset],
                         r = buffer[index + rOffset],
                         g = buffer[index + gOffset];

                    var         currentPixel = new RasterColor(r, g, b);
                    RasterColor bestColor    = FindClosestColor(currentPixel, ditheringPalette, colorMatching);

                    var error = new int[image.BitsPerPixel == 24 ? 3 : 4];
                    error[rOffset] = r - bestColor.R;
                    error[gOffset] = g - bestColor.G;
                    error[bOffset] = b - bestColor.B;

                    buffer[index + bOffset] = bestColor.B;
                    buffer[index + rOffset] = bestColor.R;
                    buffer[index + gOffset] = bestColor.G;

                    if (matrix?.Cells == null)
                    {
                        continue;
                    }
                    foreach (ErrorDiffusionMatrix.Cell cell in matrix.Cells)
                    {
                        int targetX = x + cell.XOffset,
                                                       targetY = y + cell.YOffset;

                        if (targetX < 0 || targetX >= image.Width)
                        {
                            continue;
                        }
                        if (targetY < 0 || targetY >= image.Height)
                        {
                            continue;
                        }

                        ApplyError(targetX, targetY, error, cell.Numerator, matrix.Denominator);
                    }
                }
            }

            SetImageBytes(image, buffer);
            return(image);
        }