private void LineAdd_Click(object sender, RoutedEventArgs e) { if (bitmapArrayWithoutLines == null) { bitmapArrayWithoutLines = new FastBitmapArray(bitmapArray); } if (multisamplingForNewLines) { //bitmapArray.CopyArea(bitmapArrayWithoutLines); int scaling = 2; bitmapArrayWithoutLines = bitmapArrayWithoutLines.ScaleUp(scaling); var l = new Line(scaling * (int)StartPointX, scaling * (int)StartPointY, scaling * (int)EndPointX, scaling * (int)EndPointY, lineColor.ScR, lineColor.ScG, lineColor.ScB, scaling * (int)lineThickness); bitmapArrayWithoutLines.DrawLine(l); bitmapArrayWithoutLines = bitmapArrayWithoutLines.ScaleDown(scaling); SetBitmapArray(bitmapArrayWithoutLines); } else { var l = new Line((int)StartPointX, (int)StartPointY, (int)EndPointX, (int)EndPointY, lineColor.ScR, lineColor.ScG, lineColor.ScB, (int)lineThickness); Lines.Add(l); bitmapArray.DrawLine(l); } }
/// <summary> /// Applies this filter in a given circular area of the given FastBitmapArray. /// </summary> /// <param name="array"></param> /// <param name="point"></param> /// <param name="diameter"></param> /// <param name="mask"></param> protected void PaintCircle(FastBitmapArray array, Point point, int diameter, bool[][] mask) { int centerX = (int)point.X; int centerY = (int)point.Y; double radius = diameter / 2; int x = centerX - (int)radius; int y = centerY - (int)radius; int xEnd = x + diameter; int yEnd = y + diameter; bool inBounds = false; array.SetBatchArea(x, y, xEnd - 1, yEnd - 1); for (int i = x; i < xEnd; i++) { for (int j = y; j < yEnd; j++) { inBounds = i >= 0 && i < array.Width && j >= 0 && j < array.Height && (i - centerX) * (i - centerX) + (j - centerY) * (j - centerY) <= radius * radius; if (inBounds && mask[i][j]) { FilterWithCorrection(array, i, j); mask[i][j] = false; } } } }
/// <summary> /// Applies this filter in a given rectangular area of the given FastBitmapArray. /// </summary> /// <param name="array"></param> /// <param name="point"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="mask"></param> protected void PaintRect(FastBitmapArray array, Point point, int width, int height, bool[][] mask) { int x = (int)point.X; int y = (int)point.Y; int xEnd = x + width; int yEnd = y + height; bool inBounds = false; array.SetBatchArea(x, y, xEnd - 1, yEnd - 1); for (int i = x; i < xEnd; i++) { for (int j = y; j < yEnd; j++) { inBounds = i >= 0 && i < array.Width && j >= 0 && j < array.Height; if (inBounds && mask[i][j]) { FilterWithCorrection(array, i, j); mask[i][j] = false; } } } }
public void SetBitmapArray(FastBitmapArray array) { bitmapArray = array; DrawingImage.Source = bitmapArray.GetBitmap(Mask.Disabled); DrawingImage.Width = bitmapArray.Width; DrawingImage.Height = bitmapArray.Height; ReinitializeMask(); SendPropertyChanged("MaxPointX"); SendPropertyChanged("MaxPointY"); }
public ShapePlayerWnd() { bitmapArrayLock = new object(); timersLock = new object(); random = new Random(); watch = new Stopwatch(); stopwatch = new Stopwatch(); stopwatch2 = new Stopwatch(); InitializeComponent(); bitmapArray = new FastBitmapArray(500, 500, 0.9, 0.9, 0.9); sun.Offset(200, 200); waves1.Offset(0, 250); waves2.Offset(40, 280); dolphin.Offset(70, 140); try { rect1 = new Polygon(new Point(20, 20), new Point(20, 80), new Point(80, 80), new Point(80, 20)); rect2 = rect1.Copy(); rect2.Offset(30, 30); rect3 = rect1.Clip(rect2); trig1 = new Polygon(new Point(220, 80), new Point(280, 20), new Point(280, 80)); trig2 = trig1.Copy(); trig2.Offset(15, 15); trig3 = trig1.Clip(trig2); } catch (Exception e) { Trace.WriteLine(e.ToString()); } reinitializeDisplayedBitmap = true; timer = new DispatcherTimer(new TimeSpan(0, 0, 0, 0, 30), DispatcherPriority.Background, TimerTick, this.Dispatcher); timer.Start(); timerReport = new DispatcherTimer(new TimeSpan(0, 0, 0, 0, 1970), DispatcherPriority.Background, TimerReportTick, this.Dispatcher); timerReport.Start(); watch.Start(); }
/// <summary> /// Applies the filter at given point of a given FastBitmapArray, using given shape of given size. /// </summary> /// <param name="array">array on which the filter will be applied</param> /// <param name="shape">shape of the brush</param> /// <param name="point">central point of the brush</param> /// <param name="size"> diameter of the brush</param> /// <param name="mask">masking array</param> public void ApplyAt(FastBitmapArray array, BrushShapes shape, Point point, int size, bool[][] mask) { switch (shape) { case BrushShapes.Fill: Fill(array, mask); break; case BrushShapes.Square: PaintRect(array, new Point(point.X - size / 2, point.Y - size / 2), size, size, mask); break; case BrushShapes.Circle: PaintCircle(array, point, size, mask); break; } }
private void DrawingArea_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (sender == null || !(sender is Canvas)) { throw new ArgumentException("expected only Canvas", "sender"); } var canvas = (Canvas)sender; if (!canvas.CaptureMouse()) { throw new InvalidOperationException("cannot draw if mouse cannot captured"); } switch (tool) { case Tools.Filtering: { //Status = "painting"; bitmapArrayWithoutLines = null; Lines.Clear(); } break; case Tools.Line: { //Status = "adding line"; currentLineStart = new Point(e.GetPosition(canvas).X, e.GetPosition(canvas).Y); if (bitmapArrayTemp == null) { currentLineEnd = currentLineStart; bitmapArrayTemp = new FastBitmapArray(bitmapArray); } } break; default: return; } keyIsDown = true; DrawingArea_MouseDownOrMove(sender, e); }
private void UpdateImageSize(int width, int height) { lock (bitmapArrayLock) { int oldWidth = bitmapArray.Width; int oldHeight = bitmapArray.Height; var newBitmapArray = new FastBitmapArray(width, height); //bool smallerWidth = width < oldWidth; //bool smallerHeight = height < oldHeight; //int diffWidth = width - oldWidth; //int diffHeight = height - oldHeight; //if (!smallerWidth && !smallerHeight) // bitmapArray.CopyAreaBatch(bitmapArray); bitmapArray = newBitmapArray; reinitializeDisplayedBitmap = true; } }
private void FilterWithCorrection(FastBitmapArray /*bitmap*/ array, int x, int y) { double red = array.GetRed(x, y); double green = array.GetGreen(x, y); double blue = array.GetBlue(x, y); double redNew = FilterRed(red, green, blue); double greenNew = FilterGreen(red, green, blue); double blueNew = FilterBlue(red, green, blue); if (redNew < 0) { redNew = 0; } else if (redNew > 1) { redNew = 1; } if (greenNew < 0) { greenNew = 0; } else if (greenNew > 1) { greenNew = 1; } if (blueNew < 0) { blueNew = 0; } else if (blueNew > 1) { blueNew = 1; } array.SetPixelBatch(x, y, redNew, greenNew, blueNew); }
public FastBitmapArray Process(FastBitmapArray array, ErrorDiffusionKernelName kernelName, int levelsCount) { if (levelsCount < 2) { throw new ArgumentException("at least 2 levels are needed"); } var processed = new FastBitmapArray(array.Width, array.Height); int levelsCountLess = levelsCount - 1; double[] levels = new double[levelsCount]; // upper bounds for all levels (except for the last level, cos this one is always 1.0) double[] levelsBounds = new double[levelsCountLess]; for (int i = 0; i < levelsCount; ++i) { levels[i] = ((double)i) / levelsCountLess; if (i > 0) { levelsBounds[i - 1] = (levels[i - 1] + levels[i]) / 2; } } var matrix = Matrices[kernelName]; var matrixSum = MatricesSums[kernelName]; var matrixWidth = matrix[0].Length; var matrixHeight = matrix.Length; var currentPixelX = (matrixWidth - 1) / 2; for (int y = 0; y < array.Height; ++y) { for (int x = 0; x < array.Width; ++x) { // get color value double red = array.GetRed(x, y); double green = array.GetGreen(x, y); double blue = array.GetBlue(x, y); // add error accumulated from previous pixels red += processed.GetRed(x, y); green += processed.GetGreen(x, y); blue += processed.GetBlue(x, y); // approximate double redApprox = levels[levelsCountLess]; for (int i = 0; i < levelsCountLess; ++i) { if (red < levelsBounds[i]) { redApprox = levels[i]; break; } } double greenApprox = levels[levelsCountLess]; for (int i = 0; i < levelsCountLess; ++i) { if (green < levelsBounds[i]) { greenApprox = levels[i]; break; } } double blueApprox = levels[levelsCountLess]; for (int i = 0; i < levelsCountLess; ++i) { if (blue < levelsBounds[i]) { blueApprox = levels[i]; break; } } // calculate error double redError = red - redApprox; double greenError = green - greenApprox; double blueError = blue - blueApprox; // set current pixel value processed.SetRedBatch(x, y, redApprox); processed.SetGreenBatch(x, y, greenApprox); processed.SetBlueBatch(x, y, blueApprox); // diffuse the arror accross other pixels for (int xx = 0; xx < matrixWidth; ++xx) { for (int yy = 0; yy < matrixHeight; ++yy) { if (yy == 0 && xx <= currentPixelX) { continue; } int xxx = x + xx - currentPixelX; int yyy = y + yy; if (xxx < 0 || xxx >= array.Width || yyy >= array.Height) { continue; } double level = ((double)matrix[yy][xx]) / matrixSum; processed.SetRedBatch(xxx, yyy, processed.GetRed(xxx, yyy) + redError * level); processed.SetGreenBatch(xxx, yyy, processed.GetGreen(xxx, yyy) + greenError * level); processed.SetBlueBatch(xxx, yyy, processed.GetBlue(xxx, yyy) + blueError * level); } } } } processed.SetBatchArea(); return(processed); }
/// <summary> /// Processes the input array. /// </summary> /// <param name="array"></param> /// <param name="matrixSize"></param> /// <returns></returns> public FastBitmapArray Process(FastBitmapArray array, int matrixSize, int levelsCount) { #region old approach //var processed = new FastBitmapArray(array.Width * matrixSize, array.Height * matrixSize); //int procXmin = 0; //int procXmax = 0; //int procYmin = 0; //int procYmax = 0; //var matrix = Matrices[matrixSize]; //var matrixCoef = matrixSize * matrixSize + 1; //for (int x = 0; x < array.Width; ++x) //{ // procXmin = x * matrixSize; // procXmax = procXmin + matrixSize; // for (int y = 0; y < array.Height; ++y) // { // double red = array.GetRed(x, y); // double green = array.GetGreen(x, y); // double blue = array.GetBlue(x, y); // procYmin = y * matrixSize; // procYmax = procYmin + matrixSize; // for (int xx = procXmin, xxx = 0; xx < procXmax; ++xx, ++xxx) // for (int yy = procYmin, yyy = 0; yy < procYmax; ++yy, ++yyy) // { // double matrixValue = ((double)matrix[xxx][yyy]) / matrixCoef; // processed.SetRed(xx, yy, red > matrixValue ? 1 : 0); // processed.SetGreen(xx, yy, green > matrixValue ? 1 : 0); // processed.SetBlue(xx, yy, blue > matrixValue ? 1 : 0); // } // } //} #endregion // new approach: var processed = new FastBitmapArray(array.Width, array.Height); int levelsCountLess = levelsCount - 1; var matrix = Matrices[matrixSize]; var matrixCoef = matrixSize * matrixSize + 1; double matrixLevel = 1.0 / levelsCountLess; double[] levels = new double[levelsCount]; // upper bounds for all levels (except for the last level, cos this one is always 1.0) double[] levelsBounds = new double[levelsCountLess]; for (int i = 0; i < levelsCount; ++i) { levels[i] = ((double)i) / levelsCountLess; if (i > 0) { levelsBounds[i - 1] = (levels[i - 1] + levels[i]) / 2; } if (i > 0 && i < levelsCount - 1) { levels[i] += 0.5 / (levelsCountLess * (matrixCoef - 1) + 1); } } int matrixX = 0; int matrixY = 0; for (int x = 0; x < array.Width; ++x) { for (int y = 0; y < array.Height; ++y) { double matrixValue = matrixLevel * ((double)matrix[matrixY][matrixX]) / matrixCoef; double red = array.GetRed(x, y); double green = array.GetGreen(x, y); double blue = array.GetBlue(x, y); // approximation double redApprox = processOnePixel(red, levels, levelsBounds, levelsCountLess, matrixValue); double greenApprox = processOnePixel(green, levels, levelsBounds, levelsCountLess, matrixValue); double blueApprox = processOnePixel(blue, levels, levelsBounds, levelsCountLess, matrixValue); processed.SetRedBatch(x, y, redApprox); processed.SetGreenBatch(x, y, greenApprox); processed.SetBlueBatch(x, y, blueApprox); ++matrixY; if (matrixY == matrixSize) { matrixY = 0; } } ++matrixX; if (matrixX == matrixSize) { matrixX = 0; } } processed.SetBatchArea(); return(processed); }
private void OptionGeneratePalette_Click(object sender, RoutedEventArgs e) { bitmapArray = new FastBitmapArray((int)DrawingScrollView.ViewportWidth, (int)DrawingScrollView.ViewportHeight); bitmapArrayWithoutLines = null; bitmapArray.SetBatchArea(0, 0, bitmapArray.Width - 1, bitmapArray.Height - 1); double xJump = 1.0 / bitmapArray.Width; int ySegment = bitmapArray.Height / (1 + 3 + 3 + 3 + 3); //double xJump = 1.0 / bitmapArray.Width; for (int x = 0; x < bitmapArray.Width; ++x) { int y = 0; int yMax = ySegment; for (; y < yMax; ++y) { bitmapArray.SetRedBatch(x, y, x * xJump); bitmapArray.SetGreenBatch(x, y, x * xJump); bitmapArray.SetBlueBatch(x, y, x * xJump); } yMax += ySegment; for (; y < yMax; ++y) { bitmapArray.SetRedBatch(x, y, x * xJump); } yMax += ySegment; for (; y < yMax; ++y) { bitmapArray.SetGreenBatch(x, y, x * xJump); } yMax += ySegment; for (; y < yMax; ++y) { bitmapArray.SetBlueBatch(x, y, x * xJump); } yMax += ySegment; for (; y < yMax; ++y) { bitmapArray.SetRedBatch(x, y, x * xJump); bitmapArray.SetGreenBatch(x, y, x * xJump); //bitmapArray.SetBlueBatch(x, y, x * xJump); } yMax += ySegment; for (; y < yMax; ++y) { //bitmapArray.SetRedBatch(x, y, x * xJump); bitmapArray.SetGreenBatch(x, y, x * xJump); bitmapArray.SetBlueBatch(x, y, x * xJump); } yMax += ySegment; for (; y < yMax; ++y) { bitmapArray.SetRedBatch(x, y, x * xJump); //bitmapArray.SetGreenBatch(x, y, x * xJump); bitmapArray.SetBlueBatch(x, y, x * xJump); } yMax += ySegment; for (; y < yMax; ++y) { bitmapArray.SetRedBatch(x, y, x * xJump); bitmapArray.SetGreenBatch(x, y, 1); bitmapArray.SetBlueBatch(x, y, 1); } yMax += ySegment; for (; y < yMax; ++y) { bitmapArray.SetRedBatch(x, y, 1); bitmapArray.SetGreenBatch(x, y, x * xJump); bitmapArray.SetBlueBatch(x, y, 1); } yMax += ySegment; for (; y < yMax; ++y) { bitmapArray.SetRedBatch(x, y, 1); bitmapArray.SetGreenBatch(x, y, 1); bitmapArray.SetBlueBatch(x, y, x * xJump); } yMax += ySegment; for (; y < yMax; ++y) { bitmapArray.SetRedBatch(x, y, x * xJump); bitmapArray.SetGreenBatch(x, y, x * xJump); bitmapArray.SetBlueBatch(x, y, 1); } yMax += ySegment; for (; y < yMax; ++y) { bitmapArray.SetRedBatch(x, y, 1); bitmapArray.SetGreenBatch(x, y, x * xJump); bitmapArray.SetBlueBatch(x, y, x * xJump); } yMax += ySegment; for (; y < yMax; ++y) { bitmapArray.SetRedBatch(x, y, x * xJump); bitmapArray.SetGreenBatch(x, y, 1); bitmapArray.SetBlueBatch(x, y, x * xJump); } } DrawingImage.Source = bitmapArray.GetBitmap(Mask.Disabled); DrawingImage.Width = bitmapArray.Width; DrawingImage.Height = bitmapArray.Height; ReinitializeMask(); if (latestFileName != null) { latestFileName = null; OptionReload.IsEnabled = false; } }
private void DrawingArea_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (sender == null || !(sender is Canvas)) { throw new ArgumentException("expected only Canvas", "sender"); } //Status = "ready"; var canvas = (Canvas)sender; if (!keyIsDown) { return; } switch (tool) { case Tools.Filtering: { ReinitializeMask(); DrawingBrush.Visibility = Visibility.Hidden; } break; case Tools.Line: { double x = e.GetPosition(canvas).X; double y = e.GetPosition(canvas).Y; int startX = (int)currentLineStart.X; int startY = (int)currentLineStart.Y; int endX = (int)x; int endY = (int)y; bitmapArray.CopyArea(bitmapArrayTemp); if (bitmapArrayWithoutLines == null) { bitmapArrayWithoutLines = new FastBitmapArray(bitmapArray); } if (multisamplingForNewLines) { int scaling = 2; bitmapArrayWithoutLines = bitmapArrayWithoutLines.ScaleUp(scaling); var l = new Line(scaling * startX, scaling * startY, scaling * endX, scaling * endY, lineColor.ScR, lineColor.ScG, lineColor.ScB, scaling * (int)lineThickness); bitmapArrayWithoutLines.DrawLine(l); bitmapArrayWithoutLines = bitmapArrayWithoutLines.ScaleDown(scaling); SetBitmapArray(bitmapArrayWithoutLines); } else { var l = new Line(startX, startY, endX, endY, lineColor.ScR, lineColor.ScG, lineColor.ScB, (int)lineThickness); bitmapArray.DrawLine(l); bitmapArray.RefreshBitmap(Mask.Disabled); Lines.Add(l); } bitmapArrayTemp = null; //LineAdd.IsEnabled = true; //LineUpdate.IsEnabled = true; } break; } if (canvas.IsMouseCaptured) { canvas.ReleaseMouseCapture(); } if (keyIsDown) { keyIsDown = false; } }
/// <summary> /// Applies this filter on the whole given FastBitmapArray. /// </summary> /// <param name="array"></param> /// <param name="mask"></param> protected void Fill(FastBitmapArray array, bool[][] mask) { PaintRect(array, new Point(0, 0), array.Width, array.Height, mask); }
public void Apply(FastBitmapArray array, bool[][] mask) { ApplyAt(array, BrushShapes.Fill, new Point(array.Width / 2, array.Width / 2), 20, mask); }