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(); } } } }
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; } } }
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)) { }
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); } }
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); } } } }
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))); }
/// <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; }
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); } }
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; } } } } } }
/// <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); } }
/// <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; }
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); } }); }); }
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); } } } }