public override ColorBgra Apply(ColorBgra color)
            {
                byte lumi = color.GetIntensityByte();
                int  diff = Curve[lumi] - lumi;

                return(ColorBgra.FromBgraClamped(
                           color.B + diff,
                           color.G + diff,
                           color.R + diff,
                           color.A));
            }
        /// <summary>
        /// Return the final colour after error diffusion has been applied
        /// </summary>
        /// <param name="x">Current pixel position in the row</param>
        /// <param name="original">Original colour value</param>
        /// <param name="map">Colour value mapper</param>
        /// <returns></returns>
        public ColorBgra GetFinalColour(int x, ColorBgra original, Func <ColorBgra, ColorBgra> map)
        {
            var b = (int)(original.B + errorRed[0][x] + 0.5f);
            var g = (int)(original.G + errorGreen[0][x] + 0.5f);
            var r = (int)(original.R + errorRed[0][x] + 0.5f);

            var mapped = map(ColorBgra.FromBgraClamped(b, g, r, original.A));

            var errB = original.B - mapped.B;
            var errG = original.G - mapped.G;
            var errR = original.R - mapped.R;

            SpreadErrorRight(x, errB, errG, errR);
            SpreadErrorDown(x, errB, errG, errR);

            return(mapped);
        }
        public unsafe override ColorBgra Apply(ColorBgra src, int area, int *hb, int *hg, int *hr, int *ha)
        {
            int b = 0;
            int g = 0;
            int r = 0;
            int a = 0;

            for (int i = 1; i < 256; ++i)
            {
                b += i * hb[i];
                g += i * hg[i];
                r += i * hr[i];
                a += i * ha[i];
            }

            ColorBgra c = ColorBgra.FromBgraClamped(b / area, g / area, r / area, a / area);

            return(c);
        }
Exemple #4
0
        private static ColorBgra AddColor(ColorBgra original, ColorBgra addition)
        {
            if (original.A == 255)
            {
                return(original);
            }
            if (original.A == 0)
            {
                return(addition);
            }
            byte   addition_alpha = Math.Min(addition.A, (byte)(255 - original.A));
            int    total_alpha    = original.A + addition_alpha;
            double orig_frac      = original.A / (double)total_alpha;
            double add_frac       = addition_alpha / (double)total_alpha;

            return(ColorBgra.FromBgraClamped(
                       (int)(original.B * orig_frac + addition.B * add_frac),
                       (int)(original.G * orig_frac + addition.G * add_frac),
                       (int)(original.R * orig_frac + addition.R * add_frac),
                       total_alpha));
        }
Exemple #5
0
        public unsafe override ColorBgra ApplyWithAlpha(ColorBgra src, int area, int sum, int *hb, int *hg, int *hr)
        {
            //each slot of the histgram can contain up to area * 255. This will overflow an int when area > 32k
            if (area < 32768)
            {
                int b = 0;
                int g = 0;
                int r = 0;

                for (int i = 1; i < 256; ++i)
                {
                    b += i * hb[i];
                    g += i * hg[i];
                    r += i * hr[i];
                }

                int alpha = sum / area;
                int div   = area * 255;

                return(ColorBgra.FromBgraClamped(b / div, g / div, r / div, alpha));
            }
            else //use a long if an int will overflow.
            {
                long b = 0;
                long g = 0;
                long r = 0;

                for (long i = 1; i < 256; ++i)
                {
                    b += i * hb[i];
                    g += i * hg[i];
                    r += i * hr[i];
                }

                int alpha = sum / area;
                int div   = area * 255;

                return(ColorBgra.FromBgraClamped(b / div, g / div, r / div, alpha));
            }
        }
            public override ColorBgra Apply(ColorBgra color)
            {
                int i = 0;
                int h, s, v, delta;

                switch (InputMode)
                {
                case Channel.A:
                    i = Curve[color.A];
                    break;

                case Channel.R:
                    i = Curve[color.R];
                    break;

                case Channel.G:
                    i = Curve[color.G];
                    break;

                case Channel.B:
                    i = Curve[color.B];
                    break;

                case Channel.C:
                    i  = 255 - color.R;
                    i -= Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B);
                    i  = Curve[i];
                    break;

                case Channel.M:
                    i  = 255 - color.G;
                    i -= Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B);
                    i  = Curve[i];
                    break;

                case Channel.Y:
                    i  = 255 - color.B;
                    i -= Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B);
                    i  = Curve[i];
                    break;

                case Channel.K:
                    i = Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B);
                    i = Curve[i];
                    break;

                case Channel.H:
                    s     = 0;
                    v     = (color.R > color.G) ? color.R : color.G;
                    delta = 0;
                    if (color.B > v)
                    {
                        v = color.B;
                    }
                    if (v == 0)
                    {
                        s = 0;
                    }
                    else
                    {
                        int min = (color.R < color.G) ? color.R : color.G;
                        if (color.B < min)
                        {
                            min = color.B;
                        }
                        delta = v - min;
                        if (delta > 0)
                        {
                            s = CommonUtil.IntDiv(255 * delta, v);
                        }
                    }
                    if (s == 0)
                    {
                        i = 0;
                    }
                    else
                    {
                        if (color.R == v)     // Between Yellow and Magenta
                        {
                            i = CommonUtil.IntDiv(255 * (color.G - color.B), delta);
                        }
                        else if (color.G == v)     // Between Cyan and Yellow
                        {
                            i = 512 + CommonUtil.IntDiv(255 * (color.B - color.R), delta);
                        }
                        else     // Between Magenta and Cyan
                        {
                            i = 1024 + CommonUtil.IntDiv(255 * (color.R - color.G), delta);
                        }

                        if (i < 0)
                        {
                            i += 1536;
                        }

                        i = CommonUtil.IntDiv(i, 6);
                    }
                    i = Curve[i];
                    break;

                case Channel.S:
                    v = (color.R > color.G) ? color.R : color.G;
                    if (color.B > v)
                    {
                        v = color.B;
                    }
                    if (v == 0)
                    {
                        i = 0;
                    }
                    else
                    {
                        int min = (color.R < color.G) ? color.R : color.G;
                        if (color.B < min)
                        {
                            min = color.B;
                        }
                        delta = v - min;
                        if (delta > 0)
                        {
                            i = CommonUtil.IntDiv(255 * delta, v);
                        }
                    }
                    i = Curve[i];
                    break;

                case Channel.V:
                    i = (color.R > color.G) ? color.R : color.G;
                    if (color.B > i)
                    {
                        i = color.B;
                    }
                    i = Curve[i];
                    break;

                case Channel.L:
                    i = color.GetIntensityByte();
                    i = Curve[i];
                    break;

                default: throw new Exception();
                }
                switch (OutputMode)
                {
                case Channel.A:
                    return(ColorBgra.FromBgra(
                               color.B,
                               color.G,
                               color.R,
                               (byte)i));

                case Channel.R:
                    return(ColorBgra.FromBgra(
                               color.B,
                               color.G,
                               (byte)i,
                               color.A));

                case Channel.G:
                    return(ColorBgra.FromBgra(
                               color.B,
                               (byte)i,
                               color.R,
                               color.A));

                case Channel.B:
                    return(ColorBgra.FromBgra(
                               (byte)i,
                               color.G,
                               color.R,
                               color.A));

                case Channel.C:
                    i = (byte)(i + Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B)).Clamp(0, 255);
                    return(ColorBgra.FromBgra(
                               color.B,
                               color.G,
                               (byte)(255 - i),
                               color.A));

                case Channel.M:
                    i = (byte)(i + Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B)).Clamp(0, 255);
                    return(ColorBgra.FromBgra(
                               color.B,
                               (byte)(255 - i),
                               color.R,
                               color.A));

                case Channel.Y:
                    i = (byte)(i + Math.Min(Math.Min(255 - color.R, 255 - color.G), 255 - color.B)).Clamp(0, 255);
                    return(ColorBgra.FromBgra(
                               (byte)(255 - i),
                               color.G,
                               color.R,
                               color.A));

                case Channel.K:
                    int C = 255 - color.R;
                    int M = 255 - color.G;
                    int Y = 255 - color.B;
                    int K = Math.Min(Math.Min(C, M), Y);
                    return(ColorBgra.FromBgraClamped(
                               255 - (Y - K + i),
                               255 - (M - K + i),
                               255 - (C - K + i),
                               color.A));

                case Channel.H:
                    s     = 0;
                    v     = (color.R > color.G) ? color.R : color.G;
                    delta = 0;
                    if (color.B > v)
                    {
                        v = color.B;
                    }
                    if (v == 0)
                    {
                        s = 0;
                    }
                    else
                    {
                        int min = (color.R < color.G) ? color.R : color.G;
                        if (color.B < min)
                        {
                            min = color.B;
                        }
                        delta = v - min;
                        if (delta > 0)
                        {
                            s = CommonUtil.IntDiv(255 * delta, v);
                        }
                    }
                    i *= 6;
                    int fSector = (i & 0xff);
                    int sNumber = (i >> 8);
                    switch (sNumber)
                    {
                    case 0:
                        int tmp0 = ((s * (255 - fSector)) + 128) >> 8;
                        return(ColorBgra.FromBgra(
                                   (byte)(((v * (255 - s)) + 128) >> 8),
                                   (byte)(((v * (255 - tmp0)) + 128) >> 8),
                                   (byte)v,
                                   color.A));

                    case 1:
                        int tmp1 = ((s * fSector) + 128) >> 8;
                        return(ColorBgra.FromBgra(
                                   (byte)(((v * (255 - s)) + 128) >> 8),
                                   (byte)v,
                                   (byte)(((v * (255 - tmp1)) + 128) >> 8),
                                   color.A));

                    case 2:
                        int tmp2 = ((s * (255 - fSector)) + 128) >> 8;
                        return(ColorBgra.FromBgra(
                                   (byte)(((v * (255 - tmp2)) + 128) >> 8),
                                   (byte)v,
                                   (byte)(((v * (255 - s)) + 128) >> 8),
                                   color.A));

                    case 3:
                        int tmp3 = ((s * fSector) + 128) >> 8;
                        return(ColorBgra.FromBgra(
                                   (byte)v,
                                   (byte)(((v * (255 - tmp3)) + 128) >> 8),
                                   (byte)(((v * (255 - s)) + 128) >> 8),
                                   color.A));

                    case 4:
                        int tmp4 = ((s * (255 - fSector)) + 128) >> 8;
                        return(ColorBgra.FromBgra(
                                   (byte)v,
                                   (byte)(((v * (255 - s)) + 128) >> 8),
                                   (byte)(((v * (255 - tmp4)) + 128) >> 8),
                                   color.A));

                    case 5:
                        int tmp5 = ((s * fSector) + 128) >> 8;
                        return(ColorBgra.FromBgra(
                                   (byte)(((v * (255 - tmp5)) + 128) >> 8),
                                   (byte)(((v * (255 - s)) + 128) >> 8),
                                   (byte)v,
                                   color.A));

                    default:
                        return(new ColorBgra());
                    }

                case Channel.S:
                    s     = 0;
                    v     = (color.R > color.G) ? color.R : color.G;
                    delta = 0;
                    if (color.B > v)
                    {
                        v = color.B;
                    }
                    if (v == 0)
                    {
                        s = 0;
                    }
                    else
                    {
                        int min = (color.R < color.G) ? color.R : color.G;
                        if (color.B < min)
                        {
                            min = color.B;
                        }
                        delta = v - min;
                        if (delta > 0)
                        {
                            s = CommonUtil.IntDiv(255 * delta, v);
                        }
                    }
                    if (s == 0)
                    {
                        h = 0;
                    }
                    else
                    {
                        if (color.R == v)     // Between Yellow and Magenta
                        {
                            h = CommonUtil.IntDiv(255 * (color.G - color.B), delta);
                        }
                        else if (color.G == v)     // Between Cyan and Yellow
                        {
                            h = 512 + CommonUtil.IntDiv(255 * (color.B - color.R), delta);
                        }
                        else     // Between Magenta and Cyan
                        {
                            h = 1024 + CommonUtil.IntDiv(255 * (color.R - color.G), delta);
                        }

                        if (h < 0)
                        {
                            h += 1536;
                        }
                    }

                    int fs = (h & 0xff);
                    int sn = (h >> 8);
                    switch (sn)
                    {
                    case 0:
                        int tmp0 = ((i * (255 - fs)) + 128) >> 8;
                        return(ColorBgra.FromBgra(
                                   (byte)(((v * (255 - i)) + 128) >> 8),
                                   (byte)(((v * (255 - tmp0)) + 128) >> 8),
                                   (byte)v,
                                   color.A));

                    case 1:
                        int tmp1 = ((i * fs) + 128) >> 8;
                        return(ColorBgra.FromBgra(
                                   (byte)(((v * (255 - i)) + 128) >> 8),
                                   (byte)v,
                                   (byte)(((v * (255 - tmp1)) + 128) >> 8),
                                   color.A));

                    case 2:
                        int tmp2 = ((i * (255 - fs)) + 128) >> 8;
                        return(ColorBgra.FromBgra(
                                   (byte)(((v * (255 - tmp2)) + 128) >> 8),
                                   (byte)v,
                                   (byte)(((v * (255 - i)) + 128) >> 8),
                                   color.A));

                    case 3:
                        int tmp3 = ((i * fs) + 128) >> 8;
                        return(ColorBgra.FromBgra(
                                   (byte)v,
                                   (byte)(((v * (255 - tmp3)) + 128) >> 8),
                                   (byte)(((v * (255 - i)) + 128) >> 8),
                                   color.A));

                    case 4:
                        int tmp4 = ((i * (255 - fs)) + 128) >> 8;
                        return(ColorBgra.FromBgra(
                                   (byte)v,
                                   (byte)(((v * (255 - i)) + 128) >> 8),
                                   (byte)(((v * (255 - tmp4)) + 128) >> 8),
                                   color.A));

                    case 5:
                        int tmp5 = ((i * fs) + 128) >> 8;
                        return(ColorBgra.FromBgra(
                                   (byte)(((v * (255 - tmp5)) + 128) >> 8),
                                   (byte)(((v * (255 - i)) + 128) >> 8),
                                   (byte)v,
                                   color.A));

                    default:
                        return(new ColorBgra());
                    }

                case Channel.V:
                    int max = (color.R > color.G) ? color.R : color.G;
                    if (color.B > max)
                    {
                        max = color.B;
                    }
                    return(ColorBgra.FromBgra(
                               (byte)CommonUtil.IntDiv(color.B * i, max),
                               (byte)CommonUtil.IntDiv(color.G * i, max),
                               (byte)CommonUtil.IntDiv(color.R * i, max),
                               color.A
                               ));

                case Channel.L:
                    return(ColorBgra.FromBgraClamped(
                               color.B + i - color.GetIntensityByte(),
                               color.G + i - color.GetIntensityByte(),
                               color.R + i - color.GetIntensityByte(),
                               color.A));

                default:
                    throw new Exception();
                }
            }
Exemple #7
0
        private void Render(Rectangle rect, Surface srcSurface, Surface dstSurface)
#endif
        {
            ArgusPaintNet.Shared.Matrix kernel = this.Token.Kernel;
            float     factor    = this.Token.Factor * kernel.GetNormalizationFactor();
            int       kWidth    = kernel.ColumnCount;
            int       kHeight   = kernel.RowCount;
            Rectangle srcBounds = this.EnvironmentParameters.SourceSurface.Bounds;

            for (int y = rect.Top; y < rect.Bottom; y++)
            {
                if (this.IsCancelRequested)
                {
                    return;
                }

#if UNSAFE
                ColorBgra *[] pointers = new ColorBgra *[kHeight];
                for (int row = 0; row < kHeight; row++)
                {
                    int sy = y + row - kHeight / 2;
                    if (sy < 0 || sy >= srcBounds.Height)
                    {
                        pointers[row] = null;
                        continue;
                    }
                    pointers[row] = srcSurface.GetPointAddress(0, sy);
                }
#endif

#if UNSAFE
                for (int x = 0; x < rect.Width; x++)
#else
                for (int x = rect.Left; x < rect.Right; x++)
#endif
                {
                    float r = 0;
                    float g = 0;
                    float b = 0;

                    for (int col = 0; col < kWidth; col++)
                    {
                        int sx = x + col - kWidth / 2;
                        if (sx < 0 || sx >= srcBounds.Width)
                        {
                            continue;
                        }

                        for (int row = 0; row < kHeight; row++)
                        {
#if UNSAFE
                            if (pointers[row] == null)
                            {
                                continue;
                            }
                            ColorBgra px = pointers[row][sx];
#else
                            int sy = y + row - kHeight / 2;
                            if (sy < 0 || sy >= srcBounds.Height)
                            {
                                continue;
                            }

                            ColorBgra px = srcSurface[sx, sy];
#endif
                            r += kernel[row, col] * px.R * factor;
                            g += kernel[row, col] * px.G * factor;
                            b += kernel[row, col] * px.B * factor;
                        }
                    }

                    dstSurface[x, y] = ColorBgra.FromBgraClamped(Math.Abs(b), Math.Abs(g), Math.Abs(r), 255);
                }
            }
        }