private void swatch_DoubleClick(object sender, System.EventArgs e)
        {
            SystemLayer.Tracing.Ping((sender as Control).Name);

            UnaryPixelOps.Level levels = ((LevelsEffectConfigToken)theEffectToken).Levels;

            using (ColorDialog cd = new ColorDialog())
            {
                if ((sender is Panel))
                {
                    cd.Color    = ((Panel)sender).BackColor;
                    cd.AnyColor = true;

                    if (cd.ShowDialog(this) == DialogResult.OK)
                    {
                        ColorBgra col = ColorBgra.FromColor(cd.Color);

                        if (sender == swatchInLow)
                        {
                            levels.ColorInLow = col;
                        }
                        else if (sender == swatchInHigh)
                        {
                            levels.ColorInHigh = col;
                        }
                        else if (sender == swatchOutLow)
                        {
                            levels.ColorOutLow = col;
                        }
                        else if (sender == swatchOutMid)
                        {
                            ColorBgra lo     = levels.ColorInLow;
                            ColorBgra md     = ((HistogramRgb)histogramInput.Histogram).GetMeanColor();
                            ColorBgra hi     = levels.ColorInHigh;
                            ColorBgra out_lo = levels.ColorOutLow;
                            ColorBgra out_hi = levels.ColorOutHigh;

                            for (int i = 0; i < 3; i++)
                            {
                                double logA    = (col[i] - out_lo[i]) / (out_hi[i] - out_lo[i]);
                                double logBase = (md[i] - lo[i]) / (hi[i] - lo[i]);
                                double logVal  = (logBase == 1.0) ? 0.0 : Math.Log(logA, logBase);

                                levels.SetGamma(i, (float)Utility.Clamp(logVal, 0.1, 10.0));
                            }
                        }
                        else if (sender == swatchOutHigh)
                        {
                            levels.ColorOutHigh = col;
                        }
                        else if (sender == swatchInHigh)
                        {
                            levels.ColorInHigh = col;
                        }

                        InitDialogFromToken();
                    }
                }
            }
        }
Пример #2
0
        IntSliderControl m_V = 100;                                      // [0,100] {!m_UseRgbPicker} Value
        #endregion

        void Render(Surface dst, Surface src, Rectangle rect)
        {
            HsvColor  hsv        = new HsvColor(m_H, m_S, m_V);
            var       bgra       = m_UseRgbPicker ? m_RgbColor : ColorBgra.FromColor(hsv.ToColor());
            var       white      = ColorBgra.FromColor(Color.White);
            var       colorToUse = ColorBgra.Lerp(white, bgra, m_TintStrength);
            ColorBgra currentPixel;

            for (int y = rect.Top; y < rect.Bottom; y++)
            {
                if (IsCancelRequested)
                {
                    return;
                }
                for (int x = rect.Left; x < rect.Right; x++)
                {
                    currentPixel = src[x, y];
                    byte r = currentPixel.R;
                    byte g = currentPixel.G;
                    byte b = currentPixel.B;
                    currentPixel.R = (byte)((int)r * (int)colorToUse.R / 255);
                    currentPixel.G = (byte)((int)g * (int)colorToUse.G / 255);
                    currentPixel.B = (byte)((int)b * (int)colorToUse.B / 255);

                    dst[x, y] = currentPixel;
                }
            }
        }
Пример #3
0
 public Level()
     : this(ColorBgra.FromColor(System.Drawing.Color.Black),
            ColorBgra.FromColor(System.Drawing.Color.White),
            new float[] { 1, 1, 1 },
            ColorBgra.FromColor(System.Drawing.Color.Black),
            ColorBgra.FromColor(System.Drawing.Color.White))
 {
 }
Пример #4
0
        private DialogResult ShowColorPicker(Control owner, Point location, bool alpha, out ColorBgra color)
        {
            using (ColorDialog cd = new ColorDialog(alpha))
            {
                cd.Color = ColorBgra.FromColor(owner.BackColor);

                DialogResult result = cd.ShowDialog(owner);
                color = cd.Color;
                return(result);
            }
        }
Пример #5
0
        protected override void OnRender(Rectangle[] renderRects, int startIndex, int length)
        {
            float           factor      = 255 / (this._upperThres - this._lowerThres);
            bool            interpolate = this._color != this._color2;
            Pair <int, int> hues        = this.GetHues(this._hueDirection);
            double          fHue        = (hues.Second - hues.First) / MathUtil.PIOver2;
            double          fSat        = (this._color2.Saturation - this._color.Saturation) / MathUtil.PIOver2;
            double          fVal        = (this._color2.Value - this._color.Value) / MathUtil.PIOver2;

            for (int i = startIndex; i < startIndex + length; i++)
            {
                Rectangle rect = renderRects[i];
                //Pair<float, float>[,] evs = this._cachedEVs.GetValues(rect);
                TensorCharacteristics[,] charact = this._cachedCharacteristics.GetValues(rect);

                for (int y = rect.Top; y < rect.Bottom; y++)
                {
                    for (int x = rect.Left; x < rect.Right; x++)
                    {
                        float ev;
                        TensorCharacteristics tChar = charact[x - rect.Left, y - rect.Top];
                        if (this._mode == Modes.Edge)
                        {
                            ev = tChar.MaxEigenvalue;
                        }
                        else
                        {
                            ev = tChar.MinEigenvalue;
                        }

                        ev -= this._lowerThres;
                        ev *= factor;
                        ev  = Math.Max(0, Math.Min(255, ev));
                        HsvColor color = this._color;
                        if (ev > 0 && interpolate)
                        {
                            double ang = Utils.NormalizePeriodic(tChar.DominantDirection - this._angle, Math.PI);
                            if (ang > MathUtil.PIOver2)
                            {
                                ang = Math.PI - ang;
                            }

                            color.Hue        = (int)Utils.NormalizePeriodic(ang * fHue + hues.First, 360);
                            color.Saturation = (int)Math.Max(0, Math.Min(100, ang * fSat + color.Saturation));
                            color.Value      = (int)Math.Max(0, Math.Min(100, ang * fVal + color.Value));
                        }
                        var c = ColorBgra.FromColor(color.ToColor());
                        this.DstArgs.Surface[x, y] = c.NewAlpha((byte)ev);
                    }
                }
            }
        }
Пример #6
0
            public static Level AutoFromLoMdHi(ColorBgra lo, ColorBgra md, ColorBgra hi)
            {
                var gamma = new float[3];

                for (int i = 0; i < 3; i++)
                {
                    if (lo[i] < md[i] && md[i] < hi[i])
                    {
                        gamma[i] = (float)Math.Log(0.5, (float)(md[i] - lo[i]) / (float)(hi[i] - lo[i])).Clamp(0.1, 10.0);
                    }
                    else
                    {
                        gamma[i] = 1.0f;
                    }
                }

                return(new Level(lo, hi, gamma, ColorBgra.FromColor(System.Drawing.Color.Black), ColorBgra.FromColor(System.Drawing.Color.White)));
            }
Пример #7
0
        /// <summary>
        /// Renders the effect over rectangular regions automatically
        /// determined and handled by Paint.NET for multithreading support.
        /// </summary>
        /// <param name="parameters">
        /// Saved settings used to restore the GUI to the same settings it was
        /// saved with last time the effect was applied.
        /// </param>
        /// <param name="dstArgs">The destination canvas.</param>
        /// <param name="srcArgs">The source canvas.</param>
        /// <param name="rois">
        /// A list of rectangular regions to split this effect into so it can
        /// be optimized by worker threads. Determined and managed by
        /// Paint.NET.
        /// </param>
        /// <param name="startIndex">
        /// The rectangle to begin rendering with. Used in Paint.NET's effect
        /// multithreading process.
        /// </param>
        /// <param name="length">
        /// The number of rectangles to render at once. Used in Paint.NET's
        /// effect multithreading process.
        /// </param>
        public override void Render(
            EffectConfigToken parameters,
            RenderArgs dstArgs,
            RenderArgs srcArgs,
            Rectangle[] rois,
            int startIndex,
            int length)
        {
            //Renders the effect if the dialog is closed and accepted.
            if (!IsCancelRequested && !renderReady)
            {
                var src = srcArgs.Surface;
                var dst = dstArgs.Surface;
                PersistentSettings token     = (PersistentSettings)dlg.EffectToken;
                Rectangle          selection = EnvironmentParameters.GetSelection(srcArgs.Bounds).GetBoundsInt();

                //Something happened, so this must be the final render.
                if (StaticSettings.dialogResult != StaticSettings.DialogResult.Default)
                {
                    renderReady = true;
                }

                if (StaticSettings.dialogResult ==
                    StaticSettings.DialogResult.StoringImage)
                {
                    if (selection.Width < 1 || selection.Height < 1)
                    {
                        MessageBox.Show("The size of the current selection " +
                                        "must match the size of the stored image to work.");
                        return;
                    }

                    //Copies the data into the token.
                    token.StoredImg = new Bitmap(selection.Width, selection.Height);
                    for (int i = 0; i < selection.Width; i++)
                    {
                        for (int j = 0; j < selection.Height; j++)
                        {
                            token.StoredImg.SetPixel(i, j, src[selection.X + i, selection.Y + j]);
                        }
                    }
                }
                else if (StaticSettings.dialogResult ==
                         StaticSettings.DialogResult.Replacing)
                {
                    if (token.StoredImg.Width != selection.Width ||
                        token.StoredImg.Height != selection.Height)
                    {
                        MessageBox.Show("The unedited image needs to be " +
                                        "stored, and the edited version selected " +
                                        "(with the same size).");
                        return;
                    }

                    for (int y = 0; y < src.Height; y++)
                    {
                        for (int x = 0; x < src.Width; x++)
                        {
                            Color pix = token.StoredImg.GetPixel(x, y);
                            if (!src[x, y].Equals(ColorBgra.FromColor(pix)))
                            {
                                if (!token.DoInvertArea)
                                {
                                    if (token.DoInvertPicture)
                                    {
                                        dst[x, y] = pix;
                                    }
                                    else
                                    {
                                        dst[x, y] = src[x, y];
                                    }
                                }
                                else
                                {
                                    dst[x, y] = ColorBgra.Transparent;
                                }
                            }
                            else
                            {
                                if (!token.DoInvertArea)
                                {
                                    dst[x, y] = ColorBgra.Transparent;
                                }
                                else
                                {
                                    if (token.DoInvertPicture)
                                    {
                                        dst[x, y] = pix;
                                    }
                                    else
                                    {
                                        dst[x, y] = src[x, y];
                                    }
                                }
                            }
                        }
                    }
                }
            }

            StaticSettings.dialogResult = StaticSettings.DialogResult.Default;
        }
Пример #8
0
        protected virtual void SecondPass(BitmapData sourceData, Bitmap output, int width, int height, Rectangle bounds)
        {
            BitmapData outputData = null;

            Color[] pallete = output.Palette.Entries;
            int     weight  = ditherLevel;

            try
            {
                outputData = output.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);

                byte * pSourceRow   = (byte *)sourceData.Scan0.ToPointer();
                Int32 *pSourcePixel = (Int32 *)pSourceRow;

                byte *pDestinationRow   = (byte *)outputData.Scan0.ToPointer();
                byte *pDestinationPixel = pDestinationRow;

                int[] errorThisRowR = new int[width + 1];
                int[] errorThisRowG = new int[width + 1];
                int[] errorThisRowB = new int[width + 1];

                for (int row = 0; row < height; row++)
                {
                    int[] errorNextRowR = new int[width + 1];
                    int[] errorNextRowG = new int[width + 1];
                    int[] errorNextRowB = new int[width + 1];

                    int ptrInc;

                    if ((row & 1) == 0)
                    {
                        pSourcePixel      = (Int32 *)pSourceRow;
                        pDestinationPixel = pDestinationRow;
                        ptrInc            = +1;
                    }
                    else
                    {
                        pSourcePixel      = (Int32 *)pSourceRow + width - 1;
                        pDestinationPixel = pDestinationRow + width - 1;
                        ptrInc            = -1;
                    }

                    for (int col = 0; col < width; ++col)
                    {
                        ColorBgra srcPixel = *(ColorBgra *)pSourcePixel;
                        ColorBgra target   = new ColorBgra();

                        target.B = Utility.ClampToByte(srcPixel.B - ((errorThisRowB[col] * weight) / 8));
                        target.G = Utility.ClampToByte(srcPixel.G - ((errorThisRowG[col] * weight) / 8));
                        target.R = Utility.ClampToByte(srcPixel.R - ((errorThisRowR[col] * weight) / 8));
                        target.A = srcPixel.A;

                        byte pixelValue        = QuantizePixel(&target);
                        *    pDestinationPixel = pixelValue;

                        ColorBgra actual = ColorBgra.FromColor(pallete[pixelValue]);

                        int errorR = actual.R - target.R;
                        int errorG = actual.G - target.G;
                        int errorB = actual.B - target.B;


                        const int a = 7;
                        const int b = 5;
                        const int c = 3;

                        int errorRa = (errorR * a) / 16;
                        int errorRb = (errorR * b) / 16;
                        int errorRc = (errorR * c) / 16;
                        int errorRd = errorR - errorRa - errorRb - errorRc;

                        int errorGa = (errorG * a) / 16;
                        int errorGb = (errorG * b) / 16;
                        int errorGc = (errorG * c) / 16;
                        int errorGd = errorG - errorGa - errorGb - errorGc;

                        int errorBa = (errorB * a) / 16;
                        int errorBb = (errorB * b) / 16;
                        int errorBc = (errorB * c) / 16;
                        int errorBd = errorB - errorBa - errorBb - errorBc;

                        errorThisRowR[col + 1] += errorRa;
                        errorThisRowG[col + 1] += errorGa;
                        errorThisRowB[col + 1] += errorBa;

                        errorNextRowR[width - col] += errorRb;
                        errorNextRowG[width - col] += errorGb;
                        errorNextRowB[width - col] += errorBb;

                        if (col != 0)
                        {
                            errorNextRowR[width - (col - 1)] += errorRc;
                            errorNextRowG[width - (col - 1)] += errorGc;
                            errorNextRowB[width - (col - 1)] += errorBc;
                        }

                        errorNextRowR[width - (col + 1)] += errorRd;
                        errorNextRowG[width - (col + 1)] += errorGd;
                        errorNextRowB[width - (col + 1)] += errorBd;

                        unchecked
                        {
                            pSourcePixel      += ptrInc;
                            pDestinationPixel += ptrInc;
                        }
                    }

                    pSourceRow += sourceData.Stride;

                    pDestinationRow += outputData.Stride;

                    errorThisRowB = errorNextRowB;
                    errorThisRowG = errorNextRowG;
                    errorThisRowR = errorNextRowR;
                }
            }

            finally
            {
                output.UnlockBits(outputData);
            }
        }
Пример #9
0
        private unsafe void DrawOverPoints(Point start, Point finish, ColorBgra colorToReplaceWith, ColorBgra colorBeingReplaced)
        {
            ColorBgra colorAdjusted = ColorBgra.FromColor(Color.Empty);
            byte      dstAlpha;
            ColorBgra colorLifted;

            Rectangle[] rectSelRegions;
            Rectangle   rectBrushArea;
            Rectangle   rectBrushRelativeOffset = new Rectangle(0, 0, 0, 0);

            // special condition for a canvas with no active selection
            // create an array of rectangles with a single rectangle
            // specifying the size of the canvas
            if (Selection.IsEmpty)
            {
                rectSelRegions = new Rectangle[] { DocumentWorkspace.Document.Bounds };
            }
            else
            {
                rectSelRegions = clipRegion.GetRegionScansReadOnlyInt();
            }

            // code ripped off from clone stamp tool
            Point direction = new Point(finish.X - start.X, finish.Y - start.Y);
            float length    = Utility.Magnitude(direction);
            float bw        = AppEnvironment.PenInfo.Width / 2;

            float fInc;

            if (length == 0.0f)
            {
                fInc = float.PositiveInfinity;
            }
            else
            {
                fInc = (float)Math.Sqrt(bw) / length;
            }

            // iterate through all points in the linear stroke
            for (float f = 0; f < 1; f += fInc)
            {
                PointF q = new PointF(finish.X * (1 - f) + f * start.X,
                                      finish.Y * (1 - f) + f * start.Y);

                Point p = Point.Round(q);

                // iterate through all rectangles
                foreach (Rectangle rectSel in rectSelRegions)
                {
                    // set the perimeter values for the rectBrushRegion rectangle
                    // so the area can be intersected with the active
                    // selection individual recSelRegion rectangle.
                    rectBrushArea = new Rectangle(p.X - halfPenWidth, p.Y - halfPenWidth, ceilingPenWidth, ceilingPenWidth);

                    // test the intersection...
                    // the perimeter values of rectBrushRegion (above)
                    // may calculate negative but
                    // *should* always be clipped to acceptable values by
                    // by the following intersection.
                    if (rectBrushArea.IntersectsWith(rectSel))
                    {
                        // a valid intersection was found.
                        // prune the brush rectangle to fit the intersection.
                        rectBrushArea.Intersect(rectSel);
                        for (int y = rectBrushArea.Top; y < rectBrushArea.Bottom; y++)
                        {
                            // create a new rectangle for an offset relative to the
                            // the brush mask
                            rectBrushRelativeOffset.X    = Math.Max(rectSel.X - (p.X - halfPenWidth), 0);
                            rectBrushRelativeOffset.Y    = Math.Max(rectSel.Y - (p.Y - halfPenWidth), 0);
                            rectBrushRelativeOffset.Size = rectBrushArea.Size;

                            ColorBgra *srcBgra;
                            ColorBgra *dstBgra;

                            try
                            {
                                // get the source address of the first pixel from the brush mask.
                                srcBgra = (ColorBgra *)brushRenderArgs.Surface.GetPointAddress(rectBrushRelativeOffset.Left,
                                                                                               rectBrushRelativeOffset.Y + (y - rectBrushArea.Y));

                                // get the address of the pixel we want to change on the canvas.
                                dstBgra = (ColorBgra *)renderArgs.Surface.GetPointAddress(rectBrushArea.Left, y);
                            }

                            catch
                            {
                                return;
                            }

                            for (int x = rectBrushArea.Left; x < rectBrushArea.Right; x++)
                            {
                                if (srcBgra->A != 0)
                                {
                                    colorLifted = *dstBgra;

                                    // hasDrawn is set if a pixel endures color replacement so that
                                    // the placed surface will be left alone, otherwise, the placed
                                    // surface will be discarded
                                    // adjust the channel color up and down based on the difference calculated
                                    // from the source.  These values are clamped to a byte.  It's possible
                                    // that the new color is too dark or too bright to take the whole range

                                    bool boolCIT  = this.IsColorInTolerance(colorLifted, colorBeingReplaced);
                                    bool boolPAAA = false;

                                    if (AppEnvironment.AntiAliasing)
                                    {
                                        boolPAAA = this.IsPointAlreadyAntiAliased(x, y);
                                    }

                                    if (boolCIT || boolPAAA)
                                    {
                                        if (boolPAAA)
                                        {
                                            colorAdjusted = (ColorBgra)AAPoints(x, y);

                                            if (penWidth < 2.0f)
                                            {
                                                colorAdjusted.B = Utility.ClampToByte(colorToReplaceWith.B + (colorAdjusted.B - colorBeingReplaced.B));
                                                colorAdjusted.G = Utility.ClampToByte(colorToReplaceWith.G + (colorAdjusted.G - colorBeingReplaced.G));
                                                colorAdjusted.R = Utility.ClampToByte(colorToReplaceWith.R + (colorAdjusted.R - colorBeingReplaced.R));
                                                colorAdjusted.A = Utility.ClampToByte(colorToReplaceWith.A + (colorAdjusted.A - colorBeingReplaced.A));
                                            }
                                        }
                                        else
                                        {
                                            colorAdjusted.B = Utility.ClampToByte(colorLifted.B + (colorToReplaceWith.B - colorBeingReplaced.B));
                                            colorAdjusted.G = Utility.ClampToByte(colorLifted.G + (colorToReplaceWith.G - colorBeingReplaced.G));
                                            colorAdjusted.R = Utility.ClampToByte(colorLifted.R + (colorToReplaceWith.R - colorBeingReplaced.R));
                                            colorAdjusted.A = Utility.ClampToByte(colorLifted.A + (colorToReplaceWith.A - colorBeingReplaced.A));
                                        }

                                        if ((srcBgra->A != 255) && AppEnvironment.AntiAliasing)
                                        {
                                            colorAdjusted.A = srcBgra->A;
                                            dstAlpha        = dstBgra->A;
                                            *dstBgra = blendOp.Apply(*dstBgra, colorAdjusted);
                                            dstBgra->A = dstAlpha;

                                            if (!this.IsPointAlreadyAntiAliased(x, y))
                                            {
                                                AAPointsAdd(x, y, colorAdjusted);
                                            }
                                        }
                                        else
                                        {
                                            colorAdjusted.A = (*dstBgra).A;
                                            *dstBgra = colorAdjusted;

                                            if (boolPAAA)
                                            {
                                                AAPointsRemove(x, y);
                                            }
                                        }

                                        hasDrawn = true;
                                    }
                                }

                                ++srcBgra;
                                ++dstBgra;
                            }
                        }
                    }
                }
            }
        }
Пример #10
0
        /// <summary>
        /// Execute a second pass through the bitmap
        /// </summary>
        /// <param name="sourceData">The source bitmap, locked into memory</param>
        /// <param name="output">The output bitmap</param>
        /// <param name="width">The width in pixels of the image</param>
        /// <param name="height">The height in pixels of the image</param>
        /// <param name="bounds">The bounding rectangle</param>
        protected virtual void SecondPass(BitmapData sourceData, Bitmap output, int width, int height, Rectangle bounds, ProgressEventHandler progressCallback)
        {
            BitmapData outputData = null;

            Color[] pallete = output.Palette.Entries;
            int     weight  = ditherLevel;

            try
            {
                // Lock the output bitmap into memory
                outputData = output.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);

                // Define the source data pointers. The source row is a byte to
                // keep addition of the stride value easier (as this is in bytes)
                byte * pSourceRow   = (byte *)sourceData.Scan0.ToPointer();
                Int32 *pSourcePixel = (Int32 *)pSourceRow;

                // Now define the destination data pointers
                byte *pDestinationRow   = (byte *)outputData.Scan0.ToPointer();
                byte *pDestinationPixel = pDestinationRow;

                int[] errorThisRowR = new int[width + 1];
                int[] errorThisRowG = new int[width + 1];
                int[] errorThisRowB = new int[width + 1];

                for (int row = 0; row < height; row++)
                {
                    int[] errorNextRowR = new int[width + 1];
                    int[] errorNextRowG = new int[width + 1];
                    int[] errorNextRowB = new int[width + 1];

                    int ptrInc;

                    if ((row & 1) == 0)
                    {
                        pSourcePixel      = (Int32 *)pSourceRow;
                        pDestinationPixel = pDestinationRow;
                        ptrInc            = +1;
                    }
                    else
                    {
                        pSourcePixel      = (Int32 *)pSourceRow + width - 1;
                        pDestinationPixel = pDestinationRow + width - 1;
                        ptrInc            = -1;
                    }

                    // Loop through each pixel on this scan line
                    for (int col = 0; col < width; ++col)
                    {
                        // Quantize the pixel
                        ColorBgra srcPixel = *(ColorBgra *)pSourcePixel;
                        ColorBgra target   = new ColorBgra();

                        target.B = Utility.ClampToByte(srcPixel.B - ((errorThisRowB[col] * weight) / 8));
                        target.G = Utility.ClampToByte(srcPixel.G - ((errorThisRowG[col] * weight) / 8));
                        target.R = Utility.ClampToByte(srcPixel.R - ((errorThisRowR[col] * weight) / 8));
                        target.A = srcPixel.A;

                        byte pixelValue        = QuantizePixel(&target);
                        *    pDestinationPixel = pixelValue;

                        ColorBgra actual = ColorBgra.FromColor(pallete[pixelValue]);

                        int errorR = actual.R - target.R;
                        int errorG = actual.G - target.G;
                        int errorB = actual.B - target.B;

                        // Floyd-Steinberg Error Diffusion:
                        // a) 7/16 error goes to x+1
                        // b) 5/16 error goes to y+1
                        // c) 3/16 error goes to x-1,y+1
                        // d) 1/16 error goes to x+1,y+1

                        const int a = 7;
                        const int b = 5;
                        const int c = 3;

                        int errorRa = (errorR * a) / 16;
                        int errorRb = (errorR * b) / 16;
                        int errorRc = (errorR * c) / 16;
                        int errorRd = errorR - errorRa - errorRb - errorRc;

                        int errorGa = (errorG * a) / 16;
                        int errorGb = (errorG * b) / 16;
                        int errorGc = (errorG * c) / 16;
                        int errorGd = errorG - errorGa - errorGb - errorGc;

                        int errorBa = (errorB * a) / 16;
                        int errorBb = (errorB * b) / 16;
                        int errorBc = (errorB * c) / 16;
                        int errorBd = errorB - errorBa - errorBb - errorBc;

                        errorThisRowR[col + 1] += errorRa;
                        errorThisRowG[col + 1] += errorGa;
                        errorThisRowB[col + 1] += errorBa;

                        errorNextRowR[width - col] += errorRb;
                        errorNextRowG[width - col] += errorGb;
                        errorNextRowB[width - col] += errorBb;

                        if (col != 0)
                        {
                            errorNextRowR[width - (col - 1)] += errorRc;
                            errorNextRowG[width - (col - 1)] += errorGc;
                            errorNextRowB[width - (col - 1)] += errorBc;
                        }

                        errorNextRowR[width - (col + 1)] += errorRd;
                        errorNextRowG[width - (col + 1)] += errorGd;
                        errorNextRowB[width - (col + 1)] += errorBd;

                        // unchecked is necessary because otherwise it throws a fit if ptrInc is negative.
                        unchecked
                        {
                            pSourcePixel      += ptrInc;
                            pDestinationPixel += ptrInc;
                        }
                    }

                    // Add the stride to the source row
                    pSourceRow += sourceData.Stride;

                    // And to the destination row
                    pDestinationRow += outputData.Stride;

                    if (progressCallback != null)
                    {
                        progressCallback(this, new ProgressEventArgs(100.0 * (0.5 + ((double)(row + 1) / (double)height) / 2.0)));
                    }

                    errorThisRowB = errorNextRowB;
                    errorThisRowG = errorNextRowG;
                    errorThisRowR = errorNextRowR;
                }
            }

            finally
            {
                // Ensure that I unlock the output bits
                output.UnlockBits(outputData);
            }
        }
Пример #11
0
        /// <summary>
        /// Renders the effect over rectangular regions automatically
        /// determined and handled by Paint.NET for multithreading support.
        /// </summary>
        /// <param name="parameters">
        /// Saved settings used to restore the GUI to the same settings it was
        /// saved with last time the effect was applied.
        /// </param>
        /// <param name="dstArgs">The destination canvas.</param>
        /// <param name="srcArgs">The source canvas.</param>
        /// <param name="rois">
        /// A list of rectangular regions to split this effect into so it can
        /// be optimized by worker threads. Determined and managed by
        /// Paint.NET.
        /// </param>
        /// <param name="startIndex">
        /// The rectangle to begin rendering with. Used in Paint.NET's effect
        /// multithreading process.
        /// </param>
        /// <param name="length">
        /// The number of rectangles to render at once. Used in Paint.NET's
        /// effect multithreading process.
        /// </param>
        public override void Render(
            EffectConfigToken parameters,
            RenderArgs dstArgs,
            RenderArgs srcArgs,
            Rectangle[] rois,
            int startIndex,
            int length)
        {
            //Renders the effect if the dialog is closed and accepted.
            if (!IsCancelRequested && !renderReady)
            {
                var src = srcArgs.Surface;
                var dst = dstArgs.Surface;
                PersistentSettings token     = (PersistentSettings)dlg.EffectToken;
                Rectangle          selection = EnvironmentParameters.GetSelection(srcArgs.Bounds).GetBoundsInt();

                //Something happened, so this must be the final render.
                if (StaticSettings.dialogResult != StaticSettings.DialogResult.Default)
                {
                    renderReady = true;
                }

                if (StaticSettings.dialogResult ==
                    StaticSettings.DialogResult.StoringFirstImage)
                {
                    if (selection.Width <= 1 || selection.Height <= 1 ||
                        ((token.BmpReplacing.Width != selection.Width ||
                          token.BmpReplacing.Height != selection.Height) &&
                         (token.BmpReplacing.Width != 1 &&
                          token.BmpReplacing.Height != 1)))
                    {
                        MessageBox.Show("The image to replace and its " +
                                        "replacing image must be the same size, and " +
                                        "the selection must be larger than a pixel.");
                        return;
                    }

                    //Copies the data into the token.
                    token.BmpToReplace = new Bitmap(selection.Width, selection.Height);
                    for (int i = 0; i < selection.Width; i++)
                    {
                        for (int j = 0; j < selection.Height; j++)
                        {
                            token.BmpToReplace.SetPixel(i, j, src[selection.X + i, selection.Y + j]);
                        }
                    }
                }
                else if (StaticSettings.dialogResult ==
                         StaticSettings.DialogResult.StoringSecondImage)
                {
                    if (selection.Width <= 1 || selection.Height <= 1 ||
                        ((token.BmpToReplace.Width != selection.Width ||
                          token.BmpToReplace.Height != selection.Height) &&
                         (token.BmpToReplace.Width != 1 &&
                          token.BmpToReplace.Height != 1)))
                    {
                        MessageBox.Show("The image to replace and its " +
                                        "replacing image must be the same size, and " +
                                        "the selection must be larger than a pixel.");
                        return;
                    }

                    //Copies the data into the token.
                    token.BmpReplacing = new Bitmap(selection.Width, selection.Height);
                    for (int i = 0; i < selection.Width; i++)
                    {
                        for (int j = 0; j < selection.Height; j++)
                        {
                            token.BmpReplacing.SetPixel(i, j, src[selection.X + i, selection.Y + j]);
                        }
                    }
                }
                else if (StaticSettings.dialogResult ==
                         StaticSettings.DialogResult.Replacing)
                {
                    if (token.BmpToReplace.Width != token.BmpReplacing.Width ||
                        token.BmpToReplace.Height != token.BmpReplacing.Height ||
                        token.BmpToReplace.Width == 1 ||
                        token.BmpToReplace.Height == 1)
                    {
                        MessageBox.Show("Both images must be selected first.");
                        return;
                    }

                    List <Point> replacedPixels = new List <Point>();

                    //Looks at each pixel and compares it to the top-left
                    //corner of the first image. Skips pixels that are too
                    //far to the right or bottom to contain the entire image.
                    //Tracks the pixel location. When a match is found, all
                    //its pixels are checked. If everything matches, those
                    //pixels are replaced immediately and added to a list of
                    //pixels to skip over.
                    dst.CopySurface(src);

                    for (int y = 0; y <= src.Height - token.BmpToReplace.Height; y++)
                    {
                        for (int x = 0; x <= src.Width - token.BmpToReplace.Width; x++)
                        {
                            //Skips all pixels that have been replaced.
                            if (replacedPixels.Count > 0 &&
                                replacedPixels[0].X == x &&
                                replacedPixels[0].Y == y)
                            {
                                replacedPixels.RemoveAt(0);
                                continue;
                            }

                            //Checks if the first pixel matches.
                            if (ColorsMatch(ColorBgra.FromColor(
                                                token.BmpToReplace.GetPixel(0, 0)),
                                            src[x, y], token.Tolerance))
                            {
                                bool totalMatch = true;

                                //Checks if every pixel matches.
                                for (int yy = 0; yy < token.BmpToReplace.Height; yy++)
                                {
                                    for (int xx = 0; xx < token.BmpToReplace.Width; xx++)
                                    {
                                        if (!ColorsMatch(ColorBgra.FromColor(
                                                             token.BmpToReplace.GetPixel(xx, yy)),
                                                         src[x + xx, y + yy], token.Tolerance))
                                        {
                                            totalMatch = false;
                                            break;
                                        }
                                    }
                                    if (!totalMatch)
                                    {
                                        break;
                                    }
                                }

                                //Replaces the matching pixels. They will be skipped.
                                if (totalMatch)
                                {
                                    for (int yy = 0; yy < token.BmpReplacing.Height; yy++)
                                    {
                                        for (int xx = 0; xx < token.BmpReplacing.Width; xx++)
                                        {
                                            dst[x + xx, y + yy] = ColorBgra.FromColor(token.BmpReplacing.GetPixel(xx, yy));

                                            //All pixels except the first should be skipped.
                                            //The first has been checked already.
                                            if (xx != 0 && yy != 0)
                                            {
                                                replacedPixels.Add(new Point(x + xx, y + yy));
                                            }
                                        }
                                    }
                                    replacedPixels.OrderBy(p => p.X).ThenBy(p => p.Y);
                                }
                            }
                        }
                    }
                }
            }

            StaticSettings.dialogResult = StaticSettings.DialogResult.Default;
        }
Пример #12
0
        private void RenderOutputBackwards(Surface dst, Rectangle[] rects, RectInt32 bounds)
        {
            var center = new PointInt32(bounds.Left + bounds.Width / 2, bounds.Top + bounds.Height / 2);

            double maxValue = 0;
            object _lock    = new object();

            if (this.IsCancelRequested)
            {
                return;
            }

            Parallel.For(0, rects.Length, (i, loopStateI) =>
            {
                if (this.IsCancelRequested)
                {
                    loopStateI.Stop();
                    return;
                }
                Rectangle rect = rects[i];
                Parallel.For(rect.Top, rect.Bottom, (y, loopStateY) =>
                {
                    if (this.IsCancelRequested)
                    {
                        loopStateY.Stop();
                        return;
                    }
                    double mVal = 0;
                    for (int x = rect.Left; x < rect.Right; x++)
                    {
                        Complex val = this._fftPlanBackwards.GetOutput(x - bounds.Left, y - bounds.Top);
                        mVal        = Math.Max(mVal, val.Magnitude);
                    }
                    lock (_lock) { maxValue = Math.Max(maxValue, mVal); }
                });
            });

            double factor = 1.0 / maxValue;
            Func <double, ColorBgra> getColor = this._valueSource.GetGetColorFunc();

            if (this.IsCancelRequested)
            {
                return;
            }

            Parallel.For(0, rects.Length, (i, loopStateI) =>
            {
                if (this.IsCancelRequested)
                {
                    loopStateI.Stop();
                    return;
                }
                Rectangle rect = rects[i];
                Parallel.For(rect.Top, rect.Bottom, (y, loopStateY) =>
                {
                    if (this.IsCancelRequested)
                    {
                        loopStateY.Stop();
                        return;
                    }
                    for (int x = rect.Left; x < rect.Right; x++)
                    {
                        Complex val     = this._fftPlanBackwards.GetOutput(x - bounds.Left, y - bounds.Top);
                        ColorBgra color = getColor(val.Magnitude * factor);
                        dst[x, y]       = ColorBgra.FromColor(color);
                    }
                });
            });
        }
Пример #13
0
        void brushcombobox_DrawItem(object sender, DrawItemEventArgs e)
        {
            e.DrawBackground();
            if (e.State == DrawItemState.Selected)
            {
                e.DrawFocusRectangle();
            }

            if (e.Index == brushcombobox.Items.Count - 1)
            {
                e.Graphics.DrawString(brushcombobox.Items[e.Index].ToString(), e.Font, new SolidBrush(ColorBgra.Blend(new ColorBgra[] { ColorBgra.FromColor(e.ForeColor), ColorBgra.FromColor(e.BackColor) }).ToColor()), e.Bounds.X, e.Bounds.Y + 8);
            }
            else
            {
                if (e.Index >= 0)
                {
                    if (droppingdown)
                    {
                        var image = brushcollection[e.Index].ThumbnailAlphaOnly.CreateAliasedBitmap();
                        e.Graphics.DrawImage(image, e.Bounds.X + (32 - image.Width) / 2, e.Bounds.Y + (32 - image.Height) / 2);
                        e.Graphics.DrawString(brushcollection[e.Index].Name, e.Font, new SolidBrush(e.ForeColor), e.Bounds.X + 32, e.Bounds.Y);

                        e.Graphics.DrawString(brushcollection[e.Index].NativeSizePrettyString, e.Font, new SolidBrush(ColorBgra.Blend(new ColorBgra[] { ColorBgra.FromColor(e.ForeColor), ColorBgra.FromColor(e.BackColor) }).ToColor()), e.Bounds.X + 64, e.Bounds.Y + 16);
                    }
                    else
                    {
                        var image = brushcollection[e.Index].ThumbnailAlphaOnly.CreateAliasedBitmap();
                        e.Graphics.DrawImage(image, e.Bounds.X + (32 - image.Width) / 4, e.Bounds.Y + (32 - image.Height) / 4, image.Width / 2, image.Height / 2);
                        e.Graphics.DrawString(brushcollection[e.Index].Name, e.Font, new SolidBrush(e.ForeColor), e.Bounds.X + 16, e.Bounds.Y);
                    }
                }
            }
        }