├── .gitattributes ├── .gitignore ├── Bot_Control.pde ├── Drawbot_image_to_gcode.pde ├── Image1.pde ├── gcode.txt ├── pics ├── a1.jpg ├── b1.jpg ├── b2.jpg ├── b3.jpg ├── m1.jpg ├── p1.jpg └── s1.jpg ├── sketch.properties └── web-export ├── index.html └── processing.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /Bot_Control.pde: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // No, it's not a fancy dancy class like the snot nosed kids are doing these days. 3 | // Now get the hell off my lawn. 4 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 5 | void pen_up() { 6 | String buf = "G1 Z0"; 7 | is_pen_down = false; 8 | OUTPUT.println(buf); 9 | } 10 | 11 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | void pen_down() { 13 | String buf = "G1 Z1"; 14 | is_pen_down = true; 15 | OUTPUT.println(buf); 16 | } 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | void move_abs(int x, int y) { 20 | String buf = "G1 X" + nf(x,0) + " Y" + nf(y,0); 21 | 22 | if (x < drawing_min_x) { drawing_min_x = x; } 23 | if (x > drawing_max_x) { drawing_max_x = x; } 24 | if (y < drawing_min_y) { drawing_min_y = y; } 25 | if (y > drawing_max_y) { drawing_max_y = y; } 26 | 27 | if (is_pen_down) { 28 | stroke(0, 100, 0, 100-(squiggle_count * sharpie_dry_out)); 29 | line(x_old + center_x, y_old + center_y, x + center_x, y + center_y); 30 | } 31 | 32 | x_old = x; 33 | y_old = y; 34 | OUTPUT.println(buf); 35 | } 36 | 37 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 38 | 39 | -------------------------------------------------------------------------------- /Drawbot_image_to_gcode.pde: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // My Drawbot, "Death to Sharpie" 3 | // Jpeg to gcode simplified (kinda sorta works version, v3.2 (beta)) 4 | // 5 | // Scott Cooper, Dullbits.com, 6 | // 7 | // Open creative GPL source commons with some BSD public GNU foundation stuff sprinkled in... 8 | // If anything here is remotely useable, please give me a shout. 9 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 10 | 11 | // Constants set by user, or maybe your sister. 12 | final float paper_size_x = 32 * 25.4; 13 | final float paper_size_y = 40 * 25.4; 14 | final float image_size_x = 30 * 25.4; 15 | final float image_size_y = 35 * 25.4; 16 | final float paper_top_to_origin = 417; //mm 17 | 18 | // Super fun things to tweak. Not candy unicorn type fun, but still... 19 | final int squiggle_total = 400; // Total times to pick up the pen 20 | final int squiggle_length = 600; // Too small will fry your servo 21 | final int half_radius = 3; // How grundgy 22 | final int adjustbrightness = 8; // How fast it moves from dark to light, over draw 23 | final float sharpie_dry_out = 0.25; // Simulate the death of sharpie, zero for super sharpie 24 | final String pic_path = "pics\\a1.jpg"; 25 | 26 | //Every good program should have a shit pile of badly named globals. 27 | int screen_offset = 4; 28 | float screen_scale = 1.0; 29 | int steps_per_inch = 25; 30 | int x_old = 0; 31 | int y_old = 0; 32 | PImage img; 33 | int darkest_x = 100; 34 | int darkest_y = 100; 35 | float darkest_value; 36 | int squiggle_count; 37 | int x_offset = 0; 38 | int y_offset = 0; 39 | float drawing_scale; 40 | float drawing_scale_x; 41 | float drawing_scale_y; 42 | int drawing_min_x = 9999999; 43 | int drawing_max_x = -9999999; 44 | int drawing_min_y = 9999999; 45 | int drawing_max_y = -9999999; 46 | int center_x; 47 | int center_y; 48 | boolean is_pen_down; 49 | PrintWriter OUTPUT; // instantiation of the JAVA PrintWriter object. 50 | 51 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 52 | void setup() { 53 | size(900, 975, P2D); 54 | noSmooth(); 55 | colorMode(HSB, 360, 100, 100, 100); 56 | background(0, 0, 100); 57 | frameRate(120); 58 | 59 | OUTPUT = createWriter("gcode.txt"); 60 | pen_up(); 61 | setup_squiggles(); 62 | img.loadPixels(); 63 | } 64 | 65 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 66 | void draw() { 67 | scale(screen_scale); 68 | random_darkness_walk(); 69 | 70 | if (squiggle_count >= squiggle_total) { 71 | grid(); 72 | dump_some_useless_stuff_and_close(); 73 | noLoop(); 74 | } 75 | } 76 | 77 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 78 | void setup_squiggles() { 79 | img = loadImage(sketchPath("") + pic_path); // Load the image into the program 80 | img.loadPixels(); 81 | 82 | drawing_scale_x = image_size_x / img.width; 83 | drawing_scale_y = image_size_y / img.height; 84 | drawing_scale = min(drawing_scale_x, drawing_scale_y); 85 | 86 | println("Picture: " + pic_path); 87 | println("Image dimensions: " + img.width + " by " + img.height); 88 | println("adjustbrightness: " + adjustbrightness); 89 | println("squiggle_total: " + squiggle_total); 90 | println("squiggle_length: " + squiggle_length); 91 | println("Paper size: " + nf(paper_size_x,0,2) + " by " + nf(paper_size_y,0,2) + " " + nf(paper_size_x/25.4,0,2) + " by " + nf(paper_size_y/25.4,0,2)); 92 | println("Max image size: " + nf(image_size_x,0,2) + " by " + nf(image_size_y,0,2) + " " + nf(image_size_x/25.4,0,2) + " by " + nf(image_size_y/25.4,0,2)); 93 | println("Calc image size " + nf(img.width * drawing_scale,0,2) + " by " + nf(img.height * drawing_scale,0,2) + " " + nf(img.width * drawing_scale/25.4,0,2) + " by " + nf(img.height * drawing_scale/25.4,0,2)); 94 | println("Drawing scale: " + drawing_scale); 95 | 96 | // Used only for gcode, not screen. 97 | x_offset = int(-img.width * drawing_scale / 2.0); 98 | y_offset = - int(paper_top_to_origin - (paper_size_y - (img.height * drawing_scale)) / 2.0); 99 | println("X offset: " + x_offset); 100 | println("Y offset: " + y_offset); 101 | 102 | // Used only for screen, not gcode. 103 | center_x = int(width / 2 * (1 / screen_scale)); 104 | center_y = int(height / 2 * (1 / screen_scale) - (steps_per_inch * screen_offset)); 105 | } 106 | 107 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 108 | void grid() { 109 | // This will give you a rough idea of the size of the printed image, in inches. 110 | // Some screen scales smaller than 1.0 will sometimes display every other line 111 | // It looks like a big logic bug, but it just can't display a one pixel line scaled down well. 112 | stroke(0, 50, 100, 30); 113 | for (int xy = -30*steps_per_inch; xy <= 30*steps_per_inch; xy+=steps_per_inch) { 114 | line(xy + center_x, 0, xy + center_x, 200000); 115 | line(0, xy + center_y, 200000, xy + center_y); 116 | } 117 | 118 | stroke(0, 100, 100, 50); 119 | line(center_x, 0, center_x, 200000); 120 | line(0, center_y, 200000, center_y); 121 | } 122 | 123 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 124 | void dump_some_useless_stuff_and_close() { 125 | println ("Extreams of X: " + drawing_min_x + " thru " + drawing_max_x); 126 | println ("Extreams of Y: " + drawing_min_y + " thru " + drawing_max_y); 127 | OUTPUT.flush(); 128 | OUTPUT.close(); 129 | } 130 | 131 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 132 | 133 | -------------------------------------------------------------------------------- /Image1.pde: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | // Mostly a find darkest within radius and move there, kind of thing. 3 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | void random_darkness_walk() { 5 | int x, y; 6 | 7 | find_darkest(); 8 | x = darkest_x; 9 | y = darkest_y; 10 | squiggle_count++; 11 | 12 | find_darkest_neighbor(x, y); 13 | move_abs(int(darkest_x*drawing_scale+x_offset), int(darkest_y*drawing_scale+y_offset)); 14 | pen_down(); 15 | 16 | for (int s = 0; s < squiggle_length; s++) { 17 | find_darkest_neighbor(x, y); 18 | lighten(adjustbrightness, darkest_x, darkest_y); 19 | move_abs(int(darkest_x*drawing_scale+x_offset), int(darkest_y*drawing_scale+y_offset)); 20 | x = darkest_x; 21 | y = darkest_y; 22 | } 23 | pen_up(); 24 | } 25 | 26 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | void find_darkest_neighbor(int start_x, int start_y) { 28 | float darkest_neighbor = 256; 29 | int min_x, max_x, min_y, max_y; 30 | 31 | min_x = constrain(start_x - half_radius, half_radius, img.width - half_radius); 32 | min_y = constrain(start_y - half_radius, half_radius, img.height - half_radius); 33 | max_x = constrain(start_x + half_radius, half_radius, img.width - half_radius); 34 | max_y = constrain(start_y + half_radius, half_radius, img.height - half_radius); 35 | 36 | // One day I will test this to see if it does anything close to what I think it does. 37 | for (int x = min_x; x <= max_x; x++) { 38 | for (int y = min_y; y <= max_y; y++) { 39 | // Calculate the 1D location from a 2D grid 40 | int loc = x + y*img.width; 41 | float d = dist(start_x, start_y, x, y); 42 | if (d <= half_radius) { 43 | float r = red (img.pixels[loc]) + random(0, 0.01); // random else you get ugly horizontal lines 44 | if (r < darkest_neighbor) { 45 | darkest_x = x; 46 | darkest_y = y; 47 | darkest_neighbor = r; 48 | } 49 | } 50 | } 51 | } 52 | } 53 | 54 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 55 | void find_darkest() { 56 | darkest_value = 256; 57 | for (int x = half_radius; x < img.width - half_radius; x++) { 58 | for (int y = half_radius; y < img.height - half_radius; y++ ) { 59 | // Calculate the 1D location from a 2D grid 60 | int loc = x + y*img.width; 61 | 62 | float r = red (img.pixels[loc]); 63 | if (r < darkest_value) { 64 | darkest_x = x; 65 | darkest_y = y; 66 | darkest_value = r; 67 | } 68 | } 69 | } 70 | } 71 | 72 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 73 | void lighten(int adjustbrightness, int start_x, int start_y) { 74 | int min_x, max_x, min_y, max_y; 75 | 76 | min_x = constrain(start_x - half_radius, half_radius, img.width - half_radius); 77 | min_y = constrain(start_y - half_radius, half_radius, img.height - half_radius); 78 | max_x = constrain(start_x + half_radius, half_radius, img.width - half_radius); 79 | max_y = constrain(start_y + half_radius, half_radius, img.height - half_radius); 80 | 81 | /* 82 | for (int x = min_x; x <= max_x; x++) { 83 | for (int y = min_y; y <= max_y; y++) { 84 | float d = dist(start_x, start_y, x, y); 85 | if (d <= half_radius) { 86 | // Calculate the 1D location from a 2D grid 87 | int loc = y*img.width + x; 88 | float r = red (img.pixels[loc]); 89 | r += adjustbrightness / d; 90 | r = constrain(r,0,255); 91 | color c = color(r); 92 | img.pixels[loc] = c; 93 | } 94 | } 95 | } 96 | */ 97 | 98 | // Hey boys and girls its thedailywtf.com time, yeah..... 99 | lighten_one_pixel(adjustbrightness * 6, start_x, start_y); 100 | 101 | lighten_one_pixel(adjustbrightness * 2, start_x + 1, start_y ); 102 | lighten_one_pixel(adjustbrightness * 2, start_x - 1, start_y ); 103 | lighten_one_pixel(adjustbrightness * 2, start_x , start_y + 1); 104 | lighten_one_pixel(adjustbrightness * 2, start_x , start_y - 1); 105 | 106 | lighten_one_pixel(adjustbrightness * 1, start_x + 1, start_y + 1); 107 | lighten_one_pixel(adjustbrightness * 1, start_x - 1, start_y - 1); 108 | lighten_one_pixel(adjustbrightness * 1, start_x - 1, start_y + 1); 109 | lighten_one_pixel(adjustbrightness * 1, start_x + 1, start_y - 1); 110 | } 111 | 112 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 113 | void lighten_one_pixel(int adjustbrightness, int x, int y) { 114 | int loc = (y)*img.width + x; 115 | float r = red (img.pixels[loc]); 116 | r += adjustbrightness; 117 | r = constrain(r,0,255); 118 | color c = color(r); 119 | img.pixels[loc] = c; 120 | } 121 | 122 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 123 | 124 | -------------------------------------------------------------------------------- /pics/a1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scott-Cooper/Drawbot_image_to_gcode/cbaacd6cffc781f5ab2f64b711a48322ea710d97/pics/a1.jpg -------------------------------------------------------------------------------- /pics/b1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scott-Cooper/Drawbot_image_to_gcode/cbaacd6cffc781f5ab2f64b711a48322ea710d97/pics/b1.jpg -------------------------------------------------------------------------------- /pics/b2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scott-Cooper/Drawbot_image_to_gcode/cbaacd6cffc781f5ab2f64b711a48322ea710d97/pics/b2.jpg -------------------------------------------------------------------------------- /pics/b3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scott-Cooper/Drawbot_image_to_gcode/cbaacd6cffc781f5ab2f64b711a48322ea710d97/pics/b3.jpg -------------------------------------------------------------------------------- /pics/m1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scott-Cooper/Drawbot_image_to_gcode/cbaacd6cffc781f5ab2f64b711a48322ea710d97/pics/m1.jpg -------------------------------------------------------------------------------- /pics/p1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scott-Cooper/Drawbot_image_to_gcode/cbaacd6cffc781f5ab2f64b711a48322ea710d97/pics/p1.jpg -------------------------------------------------------------------------------- /pics/s1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Scott-Cooper/Drawbot_image_to_gcode/cbaacd6cffc781f5ab2f64b711a48322ea710d97/pics/s1.jpg -------------------------------------------------------------------------------- /sketch.properties: -------------------------------------------------------------------------------- 1 | mode.id=processing.mode.java.JavaMode 2 | mode=Java 3 | -------------------------------------------------------------------------------- /web-export/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Drawbot_Processing_v3 : Built with Processing and Processing.js 5 | 6 | 7 | 15 | 46 | 49 | 50 | 54 | 55 | 56 | 57 |
58 |
59 | 61 |

Your browser does not support the canvas tag.

62 | 63 |
64 | 67 |
68 |

Drawbot_Processing_v3

69 |

70 |

Source code: Drawbot_Processing_v3

71 |

72 | Built with Processing 73 | and Processing.js 74 |

75 |
76 | 77 | 78 | --------------------------------------------------------------------------------