Example #1
0
File: Program.cs Project: PJayB/PIC
            static SignedColor CalculateError(SignedColor delta, int x, int y, DitherPattern pattern)
            {
                if (y == 0)
                {
                    x--;
                }
                else
                {
                    x -= pattern.KernelMinX;
                }

                int mul = pattern.Kernel[y][x];

                if (mul == 0)
                {
                    return(new SignedColor());
                }
                else
                {
                    int         div = pattern.Divisor;
                    SignedColor c   = new SignedColor();
                    c.R = (delta.R * mul) / div;
                    c.G = (delta.G * mul) / div;
                    c.B = (delta.B * mul) / div;
                    c.A = (delta.A * mul) / div;
                    return(c);
                }
            }
Example #2
0
File: Program.cs Project: PJayB/PIC
            public Color Dither(int x, int y, Color c, DitherPattern pattern)
            {
                // Get the existing error at this pixel
                SignedColor e = GetError(x, y);

                // Get the quantized color
                Color q = QuantizeColor(c, e);

                // Calculate the difference
                SignedColor delta = Diff(c, q);

                // Kernel may be zero size (so we should ignore it)
                if (pattern.KernelHeight > 0)
                {
                    // First row handled differently
                    for (int i = 1; i <= pattern.KernelMaxX; ++i)
                    {
                        AddError(x + i, y, CalculateError(delta, i, 0, pattern));
                    }

                    // Process subsequent rows
                    for (int j = 1; j < pattern.KernelHeight; ++j)
                    {
                        for (int i = pattern.KernelMinX; i <= pattern.KernelMaxX; ++i)
                        {
                            AddError(x + i, y + j, CalculateError(delta, i, j, pattern));
                        }
                    }
                }

                _totalError += delta.RGBError;

                return(q);
            }
Example #3
0
File: Program.cs Project: PJayB/PIC
        static float DitherOneImage(Bitmap srcData, Bitmap dstData, DitherPattern pattern, Color transparentColorKey)
        {
            Ditherer ditherer = new Ditherer(srcData.Width, srcData.Height);

            for (int x = 0; x < srcData.Width; x++)
            {
                for (int y = 0; y < srcData.Height; y++)
                {
                    Color c = srcData.GetPixel(x, y);

                    if (c == transparentColorKey || c.A == 0)
                    {
                        dstData.SetPixel(x, y, Color.FromArgb(0));
                    }
                    else
                    {
                        dstData.SetPixel(x, y, ditherer.Dither(x, y, c, pattern));
                    }
                }
            }

            return(ditherer.RootMeanSquaredError);
        }
Example #4
0
        public static bool OrderedDither(Bitmap bmp, DitherPattern dp, ErrorDiffusion ed,
                bool fStretch, Color dark, Color bright, out Bitmap bmp1)
        {
            bmp1 = null;

            if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
                return false;

            int w = bmp.Width;
            int h = bmp.Height;

            Bitmap tmp = (Bitmap)bmp.Clone();

            ImageUtils.GrayScale(ref tmp);

            if (fStretch) ImageUtils.HistoStretch(ref tmp);

            byte[,] od22 = { { 51, 204},
                             {153, 102} };

            byte[,] od33 = { {131, 182,  105},
                             {157, 236,  26},
                             { 79, 210,  52} };

            byte[,] od332 = { { 64, 128,  64},
                             {128, 196, 128},
                             { 64, 128,  64} };

            byte[,] od44 = { { 15, 195,  60, 240},
                             {135,  75, 180, 120},
                             { 45, 225,  30, 210},
                             {165, 105, 150,  90} };

            byte[,] od442 = { {  51, 102, 204, 153},
                              { 204, 153,  51, 102},
                              { 153, 204, 102,  51},
                              { 102,  51, 153, 204} };

            byte[,] od443 = { {  51, 102, 204, 153},
                              { 204, 153,  51, 102},
                              { 102,  51, 153, 204},
                              { 153, 204, 102,  51} };

            byte[,] msk = od22;

            switch (dp)
            {
                case DitherPattern.od22: msk = od22; break;
                case DitherPattern.od33: msk = od33; break;
                case DitherPattern.od332: msk = od332; break;
                case DitherPattern.od44: msk = od44; break;
                case DitherPattern.od442: msk = od442; break;
                case DitherPattern.od443: msk = od443; break;
            }

            double[,] fs = { {       -1,       -1, 7.0/16.0},
                             { 3.0/16.0, 5.0/16.0, 1.0/16.0} };

            double[,] st = { {-1, -1,  -1, 8.0/42.0, 4.0/42.0},
                             {2.0/42.0, 4.0/42.0, 8.0/42.0, 4.0/42.0, 2.0/42.0},
                             {1.0/42.0, 2.0/42.0, 4.0/42.0, 2.0/42.0, 1.0/42.0} };

            double[,] sr = { {-1, -1,  -1, 5.0/32.0, 3.0/32.0},
                             {2.0/32.0, 4.0/32.0, 5.0/32.0, 4.0/32.0, 2.0/32.0},
                             {-1, 2.0/32.0, 3.0/32.0, 2.0/32.0, -1} };

            double[,] jjn = { {-1, -1, -1, 7.0/48.0, 5.0/48.0},
                              {3.0/48.0, 5.0/48.0, 7.0/48.0, 5.0/48.0, 3.0/48.0},
                              {1.0/48.0, 3.0/48.0, 5.0/48.0, 3.0/48.0, 1.0/48.0} };

            double[,] df = st;

            switch (ed)
            {
                case ErrorDiffusion.FloydSteinberg: df = fs; break;
                case ErrorDiffusion.Stucci: df = st; break;
                case ErrorDiffusion.Sierra: df = sr; break;
                case ErrorDiffusion.JaJuNi: df = jjn; break;
            }

            byte d8;
            bool d;
            double err;
            int xx, yy;

            int row = df.GetLength(0);
            int col = df.GetLength(1);

            int xrange = (col - 1) / 2;

            bmp1 = new Bitmap(w, h, PixelFormat.Format1bppIndexed);

            int dm = msk.GetLength(0);

            BmpProc8 src = new BmpProc8(tmp);
            BmpProc1 dst = new BmpProc1(bmp1);

            for (int y = 0; y < h; y++)
                for (int x = 0; x < w; x++)
                {
                    d8 = src[x, y];
                    d = (d8 > msk[y % dm, x % dm]);
                    dst[x, y] = d;

                    if (d) { err = d8 - 255; } else { err = d8; }

                    for (int iy = 0; iy < row; iy++)
                        for (int ix = -xrange; ix <= xrange; ix++)
                        {
                            xx = x + ix; if ((xx < 0) | (xx > w - 1)) continue;
                            yy = y + iy; if (yy > h - 1) continue;

                            if (df[iy, ix + xrange] < 0) continue;

                            src[xx, yy] = ImageUtils.AdjustByte(src[xx, yy] +
                                                           err * df[iy, ix + xrange]);
                        }

                }

            CallDispose(dst, src, tmp);

            ColorPalette cp = bmp1.Palette;
            cp.Entries[0] = dark;
            cp.Entries[1] = bright;
            bmp1.Palette = cp;

            return true;
        }