/// <summary> /// Gets the Potrace settings from the plug-in settings file. /// </summary> private void GetPotraceSettings() { Potrace.RestoreDefaults(); if (Settings.TryGetInteger("turnpolicy", out var turnpolicy)) { Potrace.turnpolicy = (TurnPolicy)turnpolicy; } if (Settings.TryGetInteger("turdsize", out var turdsize)) { Potrace.turdsize = turdsize; } if (Settings.TryGetDouble("alphamax", out var alphamax)) { Potrace.alphamax = alphamax; } if (Settings.TryGetBool("curveoptimizing", out var curveoptimizing)) { Potrace.curveoptimizing = curveoptimizing; } if (Settings.TryGetDouble("opttolerance", out var opttolerance)) { Potrace.opttolerance = opttolerance; } if (Settings.TryGetDouble("Treshold", out var Treshold)) { Potrace.Treshold = Treshold; } }
private void btnLoad_Click(object sender, RoutedEventArgs e) { Microsoft.Win32.OpenFileDialog op = new Microsoft.Win32.OpenFileDialog(); op.Title = "Select a picture"; op.Filter = "All supported graphics|*.jpg;*.jpeg;*.png|" + "JPEG (*.jpg;*.jpeg)|*.jpg;*.jpeg|" + "Portable Network Graphic (*.png)|*.png" + "|BMP Windows Bitmap (*.bmp)|*.bmp"; if (op.ShowDialog() == true) { imgPhoto.Source = new BitmapImage(new Uri(op.FileName)); save_button.IsEnabled = true; ListOfCurveArray = null; if (Bitmap != null) { Bitmap.Dispose(); } Bitmap = new Bitmap(op.FileName); refreshMatrix(); vectorize(); Svg = Potrace.Export2SVG(ListOfCurveArray, Bitmap.Width, Bitmap.Height); if (HasAtleastOneClue && !string.IsNullOrWhiteSpace(Word.Text)) { save.IsEnabled = true; } } }
/// <summary> /// Vectorize /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) { ListOfCurveArray = new ArrayList(); Potrace.turdsize = Convert.ToInt32(textBox1.Text); try { Potrace.alphamax = Convert.ToDouble(textBox3.Text); } catch { textBox3.Text = Potrace.alphamax.ToString(); } try { Potrace.opttolerance = Convert.ToDouble(textBox2.Text); } catch { textBox2.Text = Potrace.opttolerance.ToString(); } //optimize the path p, replacing sequences of Bezier segments by a //single segment when possible. Potrace.curveoptimizing = true; //checkBox3.Checked; Matrix = Potrace.BitMapToBinary(Bitmap, trackBar2.Value); Potrace.potrace_trace(Matrix, ListOfCurveArray); refreshMatrix(); }
private void EdgeDetectionRefresh() { if (image == null) { return; } Potrace.Clear(); ListOfPaths.Clear(); double scale = OrigImage.ActualHeight / image.Height; if (scale <= 0) { return; } int x = (int)(RectCutX / scale); int w = (int)(RectCutWidth / scale); int y = (int)(RectCutY / scale); int h = (int)(RectCutHeight / scale); Bitmap cutImage = CropBitmap(image, new Rectangle(x, y, w, h)); Potrace.Potrace_Trace(cutImage, ListOfPaths); EdgePathGeometry.AddListOfPaths(ListOfPaths); }
public void CsPotrace_PotraceTrace_LoadBitmap_Points() { using var bmp = getSquare(); Potrace po = new Potrace(); var result = po.PotraceTrace(bmp); var points = result[0].SelectMany(p => new dPoint[] { p.A, p.B }).ToArray(); Assert.Equal(8, points.Length); Assert.Equal(2, points[0].X); Assert.Equal(5, points[0].Y); Assert.Equal(5, points[1].X); Assert.Equal(8, points[1].Y); Assert.Equal(5, points[2].X); Assert.Equal(8, points[2].Y); Assert.Equal(8, points[3].X); Assert.Equal(5, points[3].Y); Assert.Equal(8, points[4].X); Assert.Equal(5, points[4].Y); Assert.Equal(5, points[5].X); Assert.Equal(2, points[5].Y); Assert.Equal(5, points[6].X); Assert.Equal(2, points[6].Y); Assert.Equal(2, points[7].X); Assert.Equal(5, points[7].Y); }
private List <Models.Game.Path> ConvertBitmapToStrokes(Bitmap bitmap) { bool[,] Matrix; ArrayList ListOfCurveArray; ListOfCurveArray = new ArrayList(); Matrix = Potrace.BitMapToBinary(bitmap, 150); Potrace.potrace_trace(Matrix, ListOfCurveArray); string selectedColor = "Black"; int lineSize = 11; string shape = "rond"; var listOfStrokes = new List <Models.Game.Path>(); var canvasId = Guid.NewGuid().ToString(); for (int i = 0; i < ListOfCurveArray.Count; i++) { ArrayList CurveArray = (ArrayList)ListOfCurveArray[i]; for (int j = 0; j < CurveArray.Count; j++) { Potrace.Curve[] Curves = (Potrace.Curve[])CurveArray[j]; var stroke = new Models.Game.Path(Guid.NewGuid().ToString(), canvasId, lineSize, selectedColor, false, shape); for (int k = 0; k < Curves.Length; k++) { if (Curves[k].Kind == Potrace.CurveKind.Bezier) { stroke.Coordinates.Add(new Coordinate() { X = Curves[k].A.X, Y = Curves[k].A.Y }); stroke.Coordinates.Add(new Coordinate() { X = Curves[k].ControlPointA.X, Y = Curves[k].ControlPointA.Y }); stroke.Coordinates.Add(new Coordinate() { X = Curves[k].ControlPointB.X, Y = Curves[k].ControlPointB.Y }); stroke.Coordinates.Add(new Coordinate() { X = Curves[k].B.X, Y = Curves[k].B.Y }); } else { stroke.Coordinates.Add(new Coordinate() { X = Curves[k].A.X, Y = Curves[k].A.Y }); stroke.Coordinates.Add(new Coordinate() { X = Curves[k].B.X, Y = Curves[k].B.Y }); } } listOfStrokes.Add(stroke); } } return(listOfStrokes); }
private void refreshMatrix() { if (Bitmap == null) { return; } Matrix = Potrace.BitMapToBinary(Bitmap, (int)contrastSlider.Value); refreshPicture(); }
private void refreshMatrix() { if (Bitmap == null) { return; } Matrix = Potrace.BitMapToBinary(Bitmap, trackBar2.Value); refreshPicture(); }
public void CsPotrace_PotraceTrace_LoadBitmap_CurveCount() { using var bmp = getSquare(); Potrace po = new Potrace(); var result = po.PotraceTrace(bmp); Assert.Single(result); // External List Assert.Equal(4, result[0].Count); }
private void refreshPicture() { if (Matrix == null) { return; } Bitmap b = Potrace.BinaryToBitmap(Matrix, true); imgPhoto.Source = BitmapToImageSource(b); }
public void CsPotrace_PotraceTrace_LoadBitmap_CurveCountCircle() { using var bmp = getCircle(); Potrace po = new Potrace(); var result = po.PotraceTrace(bmp); var points = result[0].SelectMany(p => new dPoint[] { p.A, p.B }).ToArray(); Assert.Equal(8, points.Length); }
private void RefreshSvg() { string svg = Potrace.getSVG(); string StdPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData, Environment.SpecialFolderOption.Create) + "\\Drawing3d.svg"; System.IO.StreamWriter W = new System.IO.StreamWriter(StdPath); W.WriteLine(svg); W.Flush(); W.Close(); webSvg.Navigate(new Uri(StdPath)); }
private void vectorize() { ListOfCurveArray = new ArrayList(); Potrace.turdsize = Convert.ToInt32(contrastSlider.Value); Potrace.curveoptimizing = true; Matrix = Potrace.BitMapToBinary(Bitmap, (int)contrastSlider.Value); Potrace.potrace_trace(Matrix, ListOfCurveArray); Bitmap s = Potrace.Export2GDIPlus(ListOfCurveArray, Bitmap.Width, Bitmap.Height); imgPhoto.Source = BitmapToImageSource(s); refreshMatrix(); }
/// <summary> /// Vectorize the image /// </summary> void Vectorize() { Bitmap = new Bitmap(loaded_Image); ListOfCurveArray = new ArrayList(); Potrace.turdsize = ignore_area_pixel; Potrace.alphamax = AlphaMax; Potrace.opttolerance = curve_tolerance; Potrace.curveoptimizing = Curveoptimizing; Matrix = Potrace.BitMapToBinary(Bitmap, tresHold); Potrace.potrace_trace(Matrix, ListOfCurveArray); ListElement_Image = new List <List <object> >(); ListOfLine = new List <LineF>(); }
private void saveAsCSVToolStripMenuItem_Click(object sender, EventArgs e) { if (ListOfCurveArray == null) { MessageBox.Show("Please vectorize the image first"); return; } if (saveFileDialog1.ShowDialog() == DialogResult.OK) { string s = Potrace.Export2SVG(ListOfCurveArray, Bitmap.Width, Bitmap.Height); System.IO.StreamWriter FS = new System.IO.StreamWriter(saveFileDialog1.FileName); FS.Write(s); FS.Close(); } }
private void ExportSVG(object sender, RoutedEventArgs e) { if (sourceImage == null) { return; } if (SaveFileDialog.ShowDialog() == true) { string svg = Potrace.getSVG(); string StdPath = SaveFileDialog.FileName; System.IO.StreamWriter W = new System.IO.StreamWriter(StdPath); W.WriteLine(svg); W.Flush(); W.Close(); } }
private void PreviewVector(Bitmap bmp) { Potrace.turdsize = (int)(UseSpotRemoval ? SpotRemoval : 2); Potrace.alphamax = UseSmoothing ? (double)Smoothing : 0.0; Potrace.opttolerance = UseOptimize ? (double)Optimize : 0.2; Potrace.curveoptimizing = UseOptimize; //optimize the path p, replacing sequences of Bezier segments by a single segment when possible. if (MustExitTH) { return; } List <List <CsPotrace.Curve> > plist = Potrace.PotraceTrace(bmp); if (MustExitTH) { return; } using (Graphics g = Graphics.FromImage(bmp)) { g.Clear(Color.White); //remove original image using (Brush fill = new SolidBrush(Color.FromArgb(FillingDirection != Direction.None ? 255 : 30, Color.Black))) Potrace.Export2GDIPlus(plist, g, fill, null, 1); //trace filling if (MustExitTH) { return; } PreviewLineByLine(bmp); //process filling with line by line preview if (MustExitTH) { return; } Potrace.Export2GDIPlus(plist, g, null, Pens.Red, 0); //trace borders if (MustExitTH) { return; } } }
/// <summary> /// Camキャプチャーメイン処理 /// </summary> void camCaptureTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) { if (!CamCaptureBusy) { try { CamCaptureBusy = true; FpsAct.Value = 1000d / (DateTime.Now - lastTime).Milliseconds; lastTime = DateTime.Now; CapturedBmp = CamNewFrame(cam); Potrace.Trace(CapturedBmp, (int)TraceThreshold, TracePitch); tracedSvgStr = traceSvgStr; tracedFaces = Potrace.TraceFaces(traceSvgStr); CapturedBmf.Value = CapturedBmp.ToBitmapFrame(); TracedBmf.Value = TracedBmp.ToBitmapFrame(); CamCaptureBusy = false; } catch (Exception) { } } }
/// <summary> /// Scrキャプチャーメイン処理 /// </summary> void scrCaptureTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) { if (!ScrCaptureBusy) { try { ScrCaptureBusy = true; FpsAct.Value = 1000d / (DateTime.Now - lastTime).Milliseconds; lastTime = DateTime.Now; CapturedBmp = ScreenCapture.Instance.CaptureScreen((int)DocPoint.X, (int)DocPoint.Y, (int)DocSize.Width, (int)DocSize.Height); CapturedBmp.Save(@"C:\Users\tg30266\Desktop\test.png"); Potrace.Trace(CapturedBmp, (int)TraceThreshold, TracePitch); tracedSvgStr = traceSvgStr; tracedFaces = Potrace.TraceFaces(traceSvgStr); CapturedBmf.Value = CapturedBmp.ToBitmapFrame(); TracedBmf.Value = TracedBmp.ToBitmapFrame(); ScrCaptureBusy = false; } catch (Exception) { ScrCaptureBusy = false; } } }
public void CsPotrace_Export2GCode_Export2GCode_0010() { using var bmp = PotraceTraceTests.getSquare(); var trace = new Potrace().PotraceTrace(bmp); // Image size is only used for DEBUG (static variable hardocded to FALSE) var gcodeLines = Potrace.Export2GCode(trace, 0, 0, 10, "ON", "OFF", bmp.Size); Assert.Equal(11, gcodeLines.Count); Assert.Equal("G0 X0.2 Y0.5", gcodeLines[0]); Assert.Equal("ON", gcodeLines[1]); Assert.Equal("G1 X0.288 Y0.712", gcodeLines[2]); Assert.Equal("G2 X0.5 Y0.8 I0.212 J-0.212", gcodeLines[3]); Assert.Equal("G2 X0.712 Y0.712 I0 J-0.3", gcodeLines[4]); Assert.Equal("G1 X0.8 Y0.5", gcodeLines[5]); Assert.Equal("G1 X0.712 Y0.288", gcodeLines[6]); Assert.Equal("G2 X0.5 Y0.2 I-0.212 J0.212", gcodeLines[7]); Assert.Equal("G2 X0.288 Y0.288 I0 J0.3", gcodeLines[8]); Assert.Equal("G1 X0.2 Y0.5", gcodeLines[9]); Assert.Equal("OFF", gcodeLines[10]); }
private void saveAsSVG(object sender, EventArgs e) { vectorize(); System.Windows.Forms.SaveFileDialog saveFileDialog = new System.Windows.Forms.SaveFileDialog(); saveFileDialog.DefaultExt = "svg"; saveFileDialog.FileName = "*.svg"; saveFileDialog.Filter = "svg files (*.svg)|*.svg"; if (saveFileDialog.ShowDialog() == DialogResult.OK) { // le fichier svg a envoyer à la bd. string s = Potrace.Export2SVG(ListOfCurveArray, Bitmap.Width, Bitmap.Height); // on ne gardera pas ça mais c'est utile pareil System.IO.StreamWriter FS = new System.IO.StreamWriter(saveFileDialog.FileName); FS.Write(s); FS.Close(); } }
public void CsPotrace_Export2GCode_Export2GCode_N5520() { using var bmp = PotraceTraceTests.getSquare(); var trace = new Potrace().PotraceTrace(bmp); // Image size is only used for DEBUG (static variable hardocded to FALSE) var gcodeLines = Potrace.Export2GCode(trace, -5, -5, 20, "ON", "OFF", bmp.Size); Assert.Equal(11, gcodeLines.Count); Assert.Equal("G0 X-4.9 Y-4.75", gcodeLines[0]); Assert.Equal("ON", gcodeLines[1]); Assert.Equal("G1 X-4.856 Y-4.644", gcodeLines[2]); Assert.Equal("G2 X-4.75 Y-4.6 I0.106 J-0.106", gcodeLines[3]); Assert.Equal("G2 X-4.644 Y-4.644 I0 J-0.15", gcodeLines[4]); Assert.Equal("G1 X-4.6 Y-4.75", gcodeLines[5]); Assert.Equal("G1 X-4.644 Y-4.856", gcodeLines[6]); Assert.Equal("G2 X-4.75 Y-4.9 I-0.106 J0.106", gcodeLines[7]); Assert.Equal("G2 X-4.856 Y-4.856 I0 J0.15", gcodeLines[8]); Assert.Equal("G1 X-4.9 Y-4.75", gcodeLines[9]); Assert.Equal("OFF", gcodeLines[10]); }
/// <summary> /// refresh picture /// </summary> private void refreshPicture() { if (Matrix == null) { return; } if (radioButton1.Checked) { Bitmap B = Potrace.BinaryToBitmap(Matrix, true); pictureBox1.Width = B.Width * (trackBar1.Value + 1); pictureBox1.Height = B.Height * (trackBar1.Value + 1); pictureBox1.Image = B; } else { Bitmap B = new Bitmap(Matrix.GetLength(0) * (trackBar2.Value + 1), Matrix.GetLength(1) * (trackBar2.Value + 1)); pictureBox1.Width = B.Width; pictureBox1.Height = B.Height; pictureBox1.Image = B; } draw(); }
public void LoadImagePotrace(Bitmap bmp, string filename, bool UseSpotRemoval, int SpotRemoval, bool UseSmoothing, decimal Smoothing, bool UseOptimize, decimal Optimize, L2LConf c) { bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); long start = Tools.HiResTimer.TotalMilliseconds; mTotalTravelOff = 0; mTotalTravelOn = 0; mEstimatedTimeOff = TimeSpan.Zero; mEstimatedTimeOn = TimeSpan.Zero; list.Clear(); mRange.ResetRange(); Potrace.turdsize = (int)(UseSpotRemoval ? SpotRemoval : 2); Potrace.alphamax = UseSmoothing ? (double)Smoothing : 0.0; Potrace.opttolerance = UseOptimize ? (double)Optimize : 0.2; Potrace.curveoptimizing = UseOptimize; //optimize the path p, replacing sequences of Bezier segments by a single segment when possible. List <List <CsPotrace.Curve> > plist = Potrace.PotraceTrace(bmp); if (c.dir != RasterConverter.ImageProcessor.Direction.None) { using (Bitmap ptb = new Bitmap(bmp.Width, bmp.Height)) { using (Graphics g = Graphics.FromImage(ptb)) { //Potrace.Export2GDIPlus(plist, g, Brushes.Black, null, (Math.Max(c.res/c.fres, 1) + 1) / 2.0f); Potrace.Export2GDIPlus(plist, g, Brushes.Black, null, Math.Max(1, c.res / c.fres)); using (Bitmap resampled = RasterConverter.ImageTransform.ResizeImage(ptb, new Size((int)(bmp.Width * c.fres / c.res), (int)(bmp.Height * c.fres / c.res)), true, InterpolationMode.HighQualityBicubic)) { //absolute list.Add(new GrblCommand("G90")); //use travel speed list.Add(new GrblCommand(String.Format("F{0}", c.travelSpeed))); //move fast to offset list.Add(new GrblCommand(String.Format("G0 X{0} Y{1}", formatnumber(c.oX), formatnumber(c.oY)))); if (c.pwm) { list.Add(new GrblCommand(String.Format("{0} S0", c.lOn))); //laser on and power to zero } else { list.Add(new GrblCommand(String.Format("{0} S255", c.lOff))); //laser off and power to max power } //set speed to markspeed list.Add(new GrblCommand(String.Format("G1 F{0}", c.markSpeed))); //relative list.Add(new GrblCommand("G91")); c.vectorfilling = true; ImageLine2Line(resampled, c); //laser off list.Add(new GrblCommand(c.lOff)); } } } } //absolute list.Add(new GrblCommand("G90")); //use travel speed list.Add(new GrblCommand(String.Format("F{0}", c.travelSpeed))); //move fast to offset list.Add(new GrblCommand(String.Format("G0 X{0} Y{1}", formatnumber(c.oX), formatnumber(c.oY)))); //laser off and power to maxPower list.Add(new GrblCommand(String.Format("{0} S{1}", c.lOff, c.maxPower))); //set speed to borderspeed list.Add(new GrblCommand(String.Format("G1 F{0}", c.borderSpeed))); //trace borders List <string> gc = Potrace.Export2GCode(plist, c.oX, c.oY, c.res, c.lOn, c.lOff, bmp.Size); foreach (string code in gc) { list.Add(new GrblCommand(code)); } //laser off list.Add(new GrblCommand(String.Format("{0}", c.lOff))); //move fast to origin list.Add(new GrblCommand("G0 X0 Y0")); Analyze(); long elapsed = Tools.HiResTimer.TotalMilliseconds - start; if (OnFileLoaded != null) { OnFileLoaded(elapsed, filename); } }
/// <summary> /// Creates the content of the dialog /// </summary> private RhinoDialogTableLayout CreateTableLayout() { // Create controls and define behaviors var ns_threshold = new NumericUpDownWithUnitParsing { ValueUpdateMode = NumericUpDownWithUnitParsingUpdateMode.WhenDoneChanging, MinValue = 0.0, MaxValue = 100.0, DecimalPlaces = 0, Increment = 1.0, ToolTip = "Weighted RGB color evaluation threshold.", Value = (int)(Potrace.Treshold * 100.0), Width = 45 }; var sld_threshold = new Slider { MinValue = 0, MaxValue = 100, TickFrequency = 25, Value = (int)(Potrace.Treshold * 100.0), Width = 220 }; ns_threshold.ValueChanged += (sender, args) => { if (m_allow_update_and_redraw) { m_allow_update_and_redraw = false; Potrace.Treshold = ns_threshold.Value / 100.0; sld_threshold.Value = (int)(Potrace.Treshold * 100.0); m_allow_update_and_redraw = true; UpdateAndRedraw(); } }; sld_threshold.ValueChanged += (sender, args) => { if (m_allow_update_and_redraw) { m_allow_update_and_redraw = false; Potrace.Treshold = sld_threshold.Value / 100.0; ns_threshold.Value = (int)(Potrace.Treshold * 100.0); m_allow_update_and_redraw = true; UpdateAndRedraw(); } }; var dd_turnpolicy = new DropDown { ToolTip = "Algorithm used to resolve ambiguities in path decomposition." }; foreach (var str in Enum.GetNames(typeof(TurnPolicy))) { dd_turnpolicy.Items.Add(str); } dd_turnpolicy.SelectedIndex = (int)Potrace.turnpolicy; dd_turnpolicy.SelectedIndexChanged += (sender, args) => { if (dd_turnpolicy.SelectedIndex != 0) { Potrace.turnpolicy = (TurnPolicy)dd_turnpolicy.SelectedIndex; UpdateAndRedraw(); } }; var ns_turdsize = new NumericUpDownWithUnitParsing { ValueUpdateMode = NumericUpDownWithUnitParsingUpdateMode.WhenDoneChanging, MinValue = 1.0, MaxValue = 100.0, DecimalPlaces = 0, Increment = 1.0, ToolTip = "Filter speckles of up to this size in pixels.", Value = Potrace.turdsize }; ns_turdsize.ValueChanged += (sender, args) => { Potrace.turdsize = (int)ns_turdsize.Value; UpdateAndRedraw(); }; var ns_alphamax = new NumericUpDownWithUnitParsing { ValueUpdateMode = NumericUpDownWithUnitParsingUpdateMode.WhenDoneChanging, MinValue = 0.0, MaxValue = 100.0, DecimalPlaces = 0, Increment = 1.0, ToolTip = "Corner rounding threshold.", Value = Potrace.alphamax }; ns_alphamax.ValueChanged += (sender, args) => { Potrace.alphamax = ns_alphamax.Value; UpdateAndRedraw(); }; var chk_curveoptimizing = new CheckBox { ThreeState = false, ToolTip = "Optimize of Bézier segments by a single segment when possible.", Checked = Potrace.curveoptimizing }; var ns_opttolerance = new NumericUpDownWithUnitParsing { ValueUpdateMode = NumericUpDownWithUnitParsingUpdateMode.WhenDoneChanging, MinValue = 0.1, MaxValue = 1.0, DecimalPlaces = 1, Increment = 0.1, Enabled = Potrace.curveoptimizing, ToolTip = "Tolerance used to optimize Bézier segments.", Value = Potrace.opttolerance }; chk_curveoptimizing.CheckedChanged += (sender, args) => { Potrace.curveoptimizing = chk_curveoptimizing.Checked.Value; ns_opttolerance.Enabled = Potrace.curveoptimizing; UpdateAndRedraw(); }; ns_opttolerance.ValueChanged += (sender, args) => { Potrace.opttolerance = ns_opttolerance.Value; UpdateAndRedraw(); }; var btn_reset = new Button { Text = "Restore Defaults" }; btn_reset.Click += (sender, args) => { m_allow_update_and_redraw = false; Potrace.RestoreDefaults(); sld_threshold.Value = (int)(Potrace.Treshold * 100.0); ns_threshold.Value = sld_threshold.Value; dd_turnpolicy.SelectedIndex = (int)Potrace.turnpolicy; ns_turdsize.Value = Potrace.turdsize; ns_alphamax.Value = Potrace.alphamax; chk_curveoptimizing.Checked = Potrace.curveoptimizing; ns_opttolerance.Value = Potrace.opttolerance; m_allow_update_and_redraw = true; UpdateAndRedraw(); }; // Layout the controls var minimum_size = new Eto.Drawing.Size(150, 0); var layout = new RhinoDialogTableLayout(false) { Spacing = new Eto.Drawing.Size(10, 8) }; layout.Rows.Add(new TableRow(new TableCell(new LabelSeparator { Text = "Vectorization options" }, true))); var panel0 = new Panel { MinimumSize = minimum_size, Content = new Label() { Text = "Threshold" } }; var table0 = new TableLayout { Padding = new Eto.Drawing.Padding(8, 0, 0, 0) }; table0.Rows.Add(new TableRow(new TableCell(panel0), new TableCell(sld_threshold, true), new TableCell(ns_threshold))); layout.Rows.Add(table0); var panel1 = new Panel { MinimumSize = minimum_size, Content = new Label() { Text = "Turn policy" } }; var table1 = new TableLayout { Padding = new Eto.Drawing.Padding(8, 0, 0, 0), Spacing = new Size(10, 8) }; table1.Rows.Add(new TableRow(new TableCell(panel1), new TableCell(dd_turnpolicy))); table1.Rows.Add(new TableRow(new TableCell(new Label() { Text = "Filter size" }), new TableCell(ns_turdsize))); table1.Rows.Add(new TableRow(new TableCell(new Label() { Text = "Corner rounding" }), new TableCell(ns_alphamax))); layout.Rows.Add(table1); layout.Rows.Add(new TableRow(new TableCell(new LabelSeparator { Text = "Curve optimization" }, true))); var panel2 = new Panel { MinimumSize = minimum_size, Content = new Label() { Text = "Optimizing" } }; var table2 = new TableLayout { Padding = new Eto.Drawing.Padding(8, 0, 0, 0), Spacing = new Size(10, 8) }; table2.Rows.Add(new TableRow(new TableCell(panel2), new TableCell(chk_curveoptimizing))); table2.Rows.Add(new TableRow(new TableCell(new Label() { Text = "Tolerance" }), new TableCell(ns_opttolerance))); table2.Rows.Add(null); table2.Rows.Add(new TableRow(new TableCell(new Label() { Text = "" }), new TableCell(btn_reset))); layout.Rows.Add(table2); return(layout); }
protected override void SolveInstance(IGH_DataAccess DA) { DA.GetData(0, ref ImgPath); int t = 0; DA.GetData(1, ref t); Potrace.Treshold = (double)t / 100; DA.GetData(2, ref Potrace.alphamax); int p = 0; DA.GetData(3, ref p); Potrace.turnpolicy = (TurnPolicy)p; DA.GetData(4, ref Potrace.turdsize); DA.GetData(5, ref Potrace.curveoptimizing); DA.GetData(6, ref Potrace.opttolerance); //DA.GetData(7, ref boundary); bool inv = false; DA.GetData(7, ref inv); bm = new Bitmap(ImgPath); bm.RotateFlip(RotateFlipType.RotateNoneFlipY); // convert png transparent background to white var b = new Bitmap(bm.Width, bm.Height); b.SetResolution(bm.HorizontalResolution, bm.VerticalResolution); using (var g = Graphics.FromImage(b)) { g.Clear(Color.White); g.DrawImageUnscaled(bm, 0, 0); } double H = bm.Height; double W = bm.Width; Rectangle3d boundary = new Rectangle3d(Plane.WorldXY, W, H); /* * // phsical size * double bh = boundary.Y.Length; * double bw = boundary.X.Length; * // scale Factor * double fh = bh / H; * double fw = bw / W; */ if (treeOutput) { DataTree <Curve> crvs = new DataTree <Curve>(); Potrace.Potrace_Trace(b, crvs, inv); DA.SetDataTree(0, crvs); } else { List <Curve> crvs = new List <Curve>(); Potrace.Potrace_Trace(b, crvs, inv); DA.SetDataList(0, crvs); } DA.SetData(1, boundary); }
/// <summary> /// Command.RunCommand override /// </summary> protected override Result RunCommand(RhinoDoc doc, RunMode mode) { Potrace.Clear(); // Prompt the user for the name of the image file to vectorize. string path = GetImageFileName(mode); if (string.IsNullOrEmpty(path)) { return(Result.Cancel); } // Creates a bitmap from the specified file. var bitmap = Image.FromFile(path) as Bitmap; if (null == bitmap) { RhinoApp.WriteLine("The specified file cannot be identifed as a supported type."); return(Result.Failure); } // Verify bitmap size if (0 == bitmap.Width || 0 == bitmap.Height) { RhinoApp.WriteLine("Error reading the specified file."); return(Result.Failure); } // Calculate scale factor so curves of a reasonable size are added to Rhino var unit_scale = (doc.ModelUnitSystem != UnitSystem.Inches) ? RhinoMath.UnitScale(UnitSystem.Inches, doc.ModelUnitSystem) : 1.0; var scale = (double)(1.0 / bitmap.HorizontalResolution * unit_scale); // I'm not convinced this is useful... if (true) { var format = $"F{doc.DistanceDisplayPrecision}"; // Print image size in pixels RhinoApp.WriteLine("Image size in pixels: {0} x {1}", bitmap.Width, bitmap.Height ); // Print image size in inches var width = (double)(bitmap.Width / bitmap.HorizontalResolution); var height = (double)(bitmap.Height / bitmap.VerticalResolution); RhinoApp.WriteLine("Image size in inches: {0} x {1}", width.ToString(format, CultureInfo.InvariantCulture), height.ToString(format, CultureInfo.InvariantCulture) ); // Image size in in model units, if needed if (doc.ModelUnitSystem != UnitSystem.Inches) { width = (double)(bitmap.Width / bitmap.HorizontalResolution * unit_scale); height = (double)(bitmap.Height / bitmap.VerticalResolution * unit_scale); RhinoApp.WriteLine("Image size in {0}: {1} x {2}", doc.ModelUnitSystem.ToString().ToLower(), width.ToString(format, CultureInfo.InvariantCulture), height.ToString(format, CultureInfo.InvariantCulture) ); } } // Convert the bitmap to an Eto bitmap var eto_bitmap = ConvertBitmapToEto(bitmap); if (null == eto_bitmap) { RhinoApp.WriteLine("Unable to convert image to Eto bitmap."); return(Result.Failure); } // 12-Jan-2021 Dale Fugier // This should prevent Eto.Drawing.BitmapData.GetPixels() from throwing an exception if (!IsCompatibleBitmap(eto_bitmap)) { RhinoApp.WriteLine("The image has an incompatible pixel format. Please select an image with 24 or 32 bits per pixel, or 8 bit indexed."); return(Result.Failure); } // This bitmap is not needed anymore, so dispose of it bitmap.Dispose(); // Gets the Potrace settings from the plug-in settings file GetPotraceSettings(); // Create the conduit, which does most of the work var conduit = new VectorizeConduit( eto_bitmap, scale, doc.ModelAbsoluteTolerance, m_select_output ? Rhino.ApplicationSettings.AppearanceSettings.SelectedObjectColor : doc.Layers.CurrentLayer.Color ) { Enabled = true }; if (mode == RunMode.Interactive) { // Show the interactive dialog box var dialog = new VectorizeDialog(doc, conduit); dialog.RestorePosition(); var result = dialog.ShowSemiModal(doc, RhinoEtoApp.MainWindow); dialog.SavePosition(); if (result != Result.Success) { conduit.Enabled = false; Potrace.Clear(); doc.Views.Redraw(); return(Result.Cancel); } } else { // Show the command line options var go = new GetOption(); go.SetCommandPrompt("Vectorization options. Press Enter when done"); go.AcceptNothing(true); while (true) { conduit.TraceBitmap(); doc.Views.Redraw(); go.ClearCommandOptions(); // IgnoreArea var turdsize_opt = new OptionInteger(Potrace.turdsize, 2, 100); var turdsize_idx = go.AddOptionInteger("FilterSize", ref turdsize_opt, "Filter speckles of up to this size in pixels"); // TurnPolicy var turnpolicy_idx = go.AddOptionEnumList("TurnPolicy", Potrace.turnpolicy); // Optimizing var curveoptimizing_opt = new OptionToggle(Potrace.curveoptimizing, "No", "Yes"); var curveoptimizing_idx = go.AddOptionToggle("Optimizing", ref curveoptimizing_opt); // Tolerance var opttolerance_opt = new OptionDouble(Potrace.opttolerance, 0.0, 1.0); var opttolerance_idx = go.AddOptionDouble("Tolerance", ref opttolerance_opt, "Optimizing tolerance"); // CornerThreshold var alphamax_opt = new OptionDouble(Potrace.alphamax, 0.0, 100.0); var alphamax_idx = go.AddOptionDouble("CornerRounding", ref alphamax_opt, "Corner rounding threshold"); // Threshold var threshold_opt = new OptionDouble(Potrace.Treshold, 0.0, 100.0); var threshold_idx = go.AddOptionDouble("Threshold", ref threshold_opt, "Threshold"); // RestoreDefaults var defaults_idx = go.AddOption("RestoreDefaults"); var res = go.Get(); if (res == GetResult.Option) { var option = go.Option(); if (null != option) { if (turdsize_idx == option.Index) { Potrace.turdsize = turdsize_opt.CurrentValue; } if (turnpolicy_idx == option.Index) { var list = Enum.GetValues(typeof(TurnPolicy)).Cast <TurnPolicy>().ToList(); Potrace.turnpolicy = list[option.CurrentListOptionIndex]; } if (curveoptimizing_idx == option.Index) { Potrace.curveoptimizing = curveoptimizing_opt.CurrentValue; } if (opttolerance_idx == option.Index) { Potrace.opttolerance = opttolerance_opt.CurrentValue; } if (alphamax_idx == option.Index) { Potrace.alphamax = alphamax_opt.CurrentValue; } if (threshold_idx == option.Index) { Potrace.Treshold = threshold_opt.CurrentValue; } if (defaults_idx == option.Index) { Potrace.RestoreDefaults(); } } continue; } if (res != GetResult.Nothing) { conduit.Enabled = false; doc.Views.Redraw(); Potrace.Clear(); return(Result.Cancel); } break; } } // Group curves var attributes = doc.CreateDefaultAttributes(); attributes.AddToGroup(doc.Groups.Add()); for (var i = 0; i < conduit.OutlineCurves.Count; i++) { var rhobj_id = doc.Objects.AddCurve(conduit.OutlineCurves[i], attributes); if (m_select_output) { var rhobj = doc.Objects.Find(rhobj_id); if (null != rhobj) { rhobj.Select(true); } } } conduit.Enabled = false; Potrace.Clear(); doc.Views.Redraw(); // Set the Potrace settings to the plug -in settings file. SetPotraceSettings(); return(Result.Success); }
private static string GetHolePath(Potrace.Curve[] Curves) { StringBuilder path = new StringBuilder(); for (int i = Curves.Length-1; i >=0 ; i--) { Potrace.Curve Curve = Curves[i]; if (i == Curves.Length - 1) { path.AppendLine("M" + Curve.B.x.ToString("0.0", enUsCulture) + " " + Curve.B.y.ToString("0.0", enUsCulture)); } if (Curve.Kind == Potrace.CurveKind.Bezier) { path.Append("C" + Curve.ControlPointB.x.ToString("0.0", enUsCulture) + " " + Curve.ControlPointB.y.ToString("0.0", enUsCulture) + " " + Curve.ControlPointA.x.ToString("0.0", enUsCulture) + " " + Curve.ControlPointA.y.ToString("0.0", enUsCulture) + " " + Curve.A.x.ToString("0.0", enUsCulture) + " " + Curve.A.y.ToString("0.0", enUsCulture)); } if (Curve.Kind == Potrace.CurveKind.Line) { path.Append("L" + Curve.B.x.ToString("0.0", enUsCulture) + " " + Curve.B.y.ToString("0.0", enUsCulture)); } if (i == 0) { path.Append("Z"); } else { path.AppendLine(""); } } return path.ToString(); }
protected override void BeforeSolveInstance() { base.BeforeSolveInstance(); Potrace.Clear(); }
protected override void SolveInstance(IGH_DataAccess DA) { // Variables Bitmap bm; GrasshopperBitmapGoo ghbm = new GrasshopperBitmapGoo(); double t = 50.0; double a = 1.0; double mts = 2; bool opt = true; double opttol = 0.2; bool inv = false; int colorCount = 2; // Get Data from Input Params if (!DA.GetData(0, ref ghbm)) { return; } if (DA.GetData(1, ref t)) { if (0.0 > t || t > 100.0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Threshold must lie between 0.0 to 100.0"); return; } } if (DA.GetData(2, ref a)) { if (0.0 > a || a > 1.0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Corner Threshold must lie between 0.0 to 1.0"); return; } } DA.GetData(3, ref mts); DA.GetData(4, ref opt); if (DA.GetData(5, ref opttol)) { if (0.0 > opttol || opttol > 1.0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Tolerance for Optimization must lie between 0.0 to 1.0"); return; } } DA.GetData(6, ref inv); if (DA.GetData(7, ref colorCount)) { if (colorCount < 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Color Count cannot be negative"); return; } } else { if (getColors) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Color Count not set. Setting 'Get Colors' to False. Please set a value for Color Count and re-enable Get Colors by right-clicking on the component"); getColors = false; } } // set Data in Potrace fields Potrace.Treshold = t / 100; Potrace.alphamax = a * (4 / 3); Potrace.turdsize = ((int)Math.Round(mts, 0, MidpointRounding.AwayFromZero)); Potrace.curveoptimizing = opt; Potrace.opttolerance = opttol; if (ghbm.IsValid && ghbm.Image != null) { bm = ghbm.Image; } else { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Invalid Bitmap"); return; } // convert png transparent background to white if (!getColors || (colorCount == 0)) { using (Bitmap b = new Bitmap(bm.Width, bm.Height)) { b.SetResolution(bm.HorizontalResolution, bm.VerticalResolution); using (Graphics g = Graphics.FromImage(b)) { g.Clear(Color.White); g.DrawImageUnscaled(bm, 0, 0); } b.RotateFlip(RotateFlipType.RotateNoneFlipY); DataTree <Curve> crvs = new DataTree <Curve>(); Potrace.Potrace_Trace(b, crvs, inv); DA.SetDataTree(0, crvs); } } else { using (Bitmap b = new Bitmap(bm.Width, bm.Height)) { b.SetResolution(bm.HorizontalResolution, bm.VerticalResolution); using (Graphics g = Graphics.FromImage(b)) { g.Clear(Color.Transparent); g.DrawImageUnscaled(bm, 0, 0); } b.RotateFlip(RotateFlipType.RotateNoneFlipY); WuQuantizer quantizer = new WuQuantizer(); Bitmap quantized = (Bitmap)quantizer.QuantizeImage(b, colorCount + 1); Color[] colors = new Color[colorCount]; Array.Copy(quantized.Palette.Entries, 0, colors, 0, colorCount); DataTree <GH_Colour> colorsOut = new DataTree <GH_Colour>(); DataTree <Curve> crvs = new DataTree <Curve>(); for (int i = 0; i < colorCount; i++) { Bitmap temp = quantized.Clone(new Rectangle(0, 0, b.Width, b.Height), PixelFormat.Format32bppArgb); var bmData = temp.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); unsafe { byte *p = (byte *)bmData.Scan0; int stopAddress = (int)p + bmData.Stride * bmData.Height; while ((int)p != stopAddress) { if (p[0] == colors[i].B && p[1] == colors[i].G && p[2] == colors[i].R && p[3] == colors[i].A) { p[0] = p[1] = p[2] = p[3] = 255; } else { p[0] = p[1] = p[2] = p[3] = 0; } p += 4; } temp.UnlockBits(bmData); List <Curve> curves = new List <Curve>(); Potrace.Potrace_Trace(temp, curves, true); crvs.AddRange(curves, new GH_Path(i)); if (inv) { Color invCol = Color.FromArgb(((int)colors[i].A), (255 - ((int)colors[i].R)), (255 - ((int)colors[i].G)), (255 - ((int)colors[i].B))); colorsOut.Add(new GH_Colour(invCol), new GH_Path(i)); } else { colorsOut.Add(new GH_Colour(colors[i]), new GH_Path(i)); } Potrace.Clear(); Potrace.Treshold = t / 100; Potrace.alphamax = a * (4 / 3); Potrace.turdsize = ((int)Math.Round(mts, 0, MidpointRounding.AwayFromZero)); Potrace.curveoptimizing = opt; Potrace.opttolerance = opttol; } } DA.SetDataTree(0, crvs); DA.SetDataTree(2, colorsOut); } } Rectangle3d boundary = new Rectangle3d(Plane.WorldXY, (double)bm.Width, (double)bm.Height); DA.SetData(1, boundary); }
/// <summary> /// Trace the bitmap using Potrace. /// </summary> public void TraceBitmap() { Clear(); Potrace.Clear(); Potrace.Potrace_EtoTrace(m_bitmap, m_path_curves); }