<html>
<div id="fb-root"></div>
<script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v16.0&appId=2727991274101093&autoLogAppEvents=1" nonce="99M2cCnM"></script>
<h1>Tin Man Draw Page</h1>
<div class="fb-like" data-href="https://thelotteryforum.com/tin-man-draw.html" data-width="" data-layout="" data-action="" data-size="" data-share="true"></div><br/>
<script type="text/javascript">
colors = [["1","Blue Green","#199ebd"],
["2","Black","#232323"],
["3","Blue Violet","#7366bd"],
["4","Violet(Purple)","#926eae"],
["5","Green","#1cac78"],
["6","Blue","#1f75fe"],
["7","Yellow Green","#c5e384"],
["8","White","#ededed"],
["9","Yellow","#fce883"],
["10","Carnation Pink","#ffaacc"],
["11","Yellow Orange","#ffb653"],
["12","Red","#ee204d"],
["13","Brown","#b5674d"],
["14","Orange","#ff7538"],
["15","Red Orange","#ff5349"],
["16","Red Violet","#c0448f"],
["17","Gray","#95918c"],
["18","Cerulean","#1dacd6"],
["19","Indigo","#5d76cb"],
["20","Green Yellow","#f0e891"],
["21","Dandelion","#fddb6d"],
["22","Apricot","#fdd9b5"],
["23","Violet Red","#f75394"],
["24","Scarlet","#fc2847"],
["25","Wisteria","#cda4de"],
["26","Sky Blue","#80daeb"],
["27","Cadet Blue","#b0b7c6"],
["28","Timberwolf","#dbd7d2"],
["29","Melon","#fdbcb4"],
["30","Peach","#ffcfab"],
["31","Tan","#faa76c"],
["32","Chestnut","#bc5d58"],
];
var varyColorBy = 20; //value to vary each color by out of 255 (plus or minus this value). changed by textbox input later
var canvas,canvas2, ctx,ctx2, flag,canvas1,ctx1 = false,
prevX = 0,
currX = 0,
prevY = 0,
currY = 0,
dot_flag = false;
var color = colors[1][2];
var lineWidth = 2;
base = 70;
top = 10;
function drawcolors(){
ctx1.clearRect(0,0,canvas1.width,canvas1.height)
for (var x=0;x<16;x++){
ctx1.fillStyle = colors[x][2];
ctx1.fillRect(x*40,0,40,40);
}
for (var x=16;x<32;x++){
ctx1.fillStyle = colors[x][2];
ctx1.fillRect((x-16)*40,40,40,40);
}
ctx1.fillStyle = "rgb(0,0,0)";
ctx1.beginPath();
ctx1.lineTo(640,70);
ctx1.lineTo(760,10);
ctx1.lineTo(760,70);
ctx1.lineTo(640,70);
ctx1.closePath();
ctx1.fill();
//draw brush size
radius = lineWidth/2.0;
ctx1.globalAlpha=0.5;
ctx1.beginPath();
ctx1.fillStyle = "red";
ctx1.arc(640+lineWidth*2,70-radius,radius, 0, 2 * Math.PI);
ctx1.fill();
ctx1.globalAlpha=1.0;
ctx1.globalCompositeOperation = "xor";
ctx1.beginPath();
ctx1.arc(640+lineWidth*2,70-radius,radius, 0, 2 * Math.PI);
ctx1.stroke();
ctx1.globalCompositeOperation = "source-over";
//draw brush size with current color
ctx1.beginPath();
ctx1.arc(800,40,radius,0,2*Math.PI);
ctx1.fillStyle = color;
ctx1.fill();
}
img = 0;
function init() {
canvas1 = document.getElementById('canvas');
ctx1 = canvas1.getContext("2d");
canvas1.addEventListener("mousedown", function (e) {
choosexy('down', e)
}, false);
canvas = document.getElementById('can');
canvas2 = document.getElementById('can2');
canvas3 = document.getElementById('can3');
ctx = canvas.getContext("2d");
ctx2 = canvas2.getContext("2d");
ctx3 = canvas3.getContext("2d");
img = document.getElementById("img");
canvas.width = img.width;
canvas.height = img.height;
canvas2.width = canvas.width;
canvas2.height = canvas.height;
canvas3.width = canvas.width;
canvas3.height = canvas.height;
w = canvas.width;
h = canvas.height;
ph = document.getElementById('ph');
ph.style.top = parseInt(canvas.height)+100+"px";
canvas2.style.left = parseInt(canvas.width)+10+"px";
canvas3.style.left = (parseInt(canvas.width)+10)*2 + "px";
ctx.lineCap = "round";
ctx2.lineCap = "round";
canvas.addEventListener("mousemove", function (e) {
findxy('move', e)
}, false);
canvas.addEventListener("mousedown", function (e) {
findxy('down', e)
}, false);
canvas.addEventListener("mouseup", function (e) {
findxy('up', e)
}, false);
canvas.addEventListener("mouseout", function (e) {
findxy('out', e)
}, false);
drawcolors();
}
strokes = [];
multistrokes = [];
strokecount = -1;
function shuffle_(array) {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle.
while (currentIndex != 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
function rgbToHex(r, g, b) {
return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}
function rgbStrToHex(rgbstring){
rgb = rgbstring;
//rgb = "rgb(0,128,255)"
values = rgb.slice(4,-1).split(',');
return rgbToHex(parseInt(values[0]),parseInt(values[1]),parseInt(values[2]));
}
const hexToRgb = hex =>
hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i
,(m, r, g, b) => '#' + r + r + g + g + b + b)
.substring(1).match(/.{2}/g)
.map(x => parseInt(x, 16));
function width_(array){
halfsize = array.length/2.0;
currentlw = array[0][5];
c = array[0][4];
currentc = hexToRgb(c);
r = parseInt(currentc[0]);
g = parseInt(currentc[1]);
b = parseInt(currentc[2]);
if (document.getElementById('varycheckbox').checked){ //if it's check we vary random within varycolorby range
varColorBy = parseInt(document.getElementById('varycolorby').value);
r = Math.min(255,Math.max(0,r+Math.random()*varColorBy*2-varColorBy));
g = Math.min(255,Math.max(0,g+Math.random()*varColorBy*2-varColorBy));
b = Math.min(255,Math.max(0,b+Math.random()*varColorBy*2-varColorBy));
}
for (var i=0;i<array.length;i++){
angle = (90-Math.abs((halfsize)-i)/(halfsize)*90.0)/360.0*2.0*3.1415;
thislw = currentlw * 0.1 + Math.sin(angle)*currentlw*1.0;
array[i][5] = thislw;
currentc = hexToRgb(c);
//document.getElementById('debug').innerHTML += currentc + ",";
if (document.getElementById('varywithinstroke').checked){ //if it's check we vary random within varycolorby range
r = parseInt(currentc[0]);
g = parseInt(currentc[1]);
b = parseInt(currentc[2]);
varColorBy = parseInt(document.getElementById('varycolorby').value);
r = Math.min(255,Math.max(0,r+Math.random()*varColorBy*2-varColorBy));
g = Math.min(255,Math.max(0,g+Math.random()*varColorBy*2-varColorBy));
b = Math.min(255,Math.max(0,b+Math.random()*varColorBy*2-varColorBy));
}
maxbrightvalue = Math.max(r,g,b);
ubound = (Math.min(maxbrightvalue*1.3,255.0))/maxbrightvalue;
lbound = 0.8;
fraction = ubound - Math.sin(angle)*(ubound-lbound);
thisr = parseInt(r*fraction);
thisg = parseInt(g*fraction);
thisb = parseInt(b*fraction);
array[i][7] = thisr;
array[i][8] = thisg;
array[i][9] = thisb;
}
return array;
}
function angleOf(cx, cy, ex, ey) {//returns angle in degrees
var dy = ey - cy;
var dx = ex - cx;
var theta = Math.atan2(dy, dx); // range (-PI, PI]
//theta *= 180 / Math.PI; // rads to degs, range (-180, 180]
//if (theta < 0) theta = 360 + theta; // range [0, 360)
return theta;
}
function strokeShuffle(){
strokes2 = [];
lsc = -1;
thisstrokes = [];
for (var i=0;i<strokes.length;i++){
sc = strokes[i][6];
if (sc!=lsc){
if (thisstrokes.length > 0){
thisstrokes = shuffle_(thisstrokes.slice());
for (var j=0;j<thisstrokes.length;j++){
strokes2.push(thisstrokes[j].slice());
}
}
thisstrokes = [];
lsc = sc;
}
thisstrokes.push(strokes[i].slice());
}
if (thisstrokes.length > 0){
thisstrokes = shuffle_(thisstrokes.slice());
for (var j=0;j<thisstrokes.length;j++){
strokes2.push(thisstrokes[j].slice());
}
}
return strokes2;
}
function strokeWidth(strokes){
strokes2 = [];
lsc = -1;
thisstrokes = [];
for (var i=0;i<strokes.length;i++){
sc = strokes[i][6];
if (sc!=lsc || i == 0){
if (thisstrokes.length > 0){
thisstrokes = width_(thisstrokes.slice());
for (var j=0;j<thisstrokes.length;j++){
strokes2.push(thisstrokes[j].slice());
}
}
thisstrokes = [];
lsc = sc;
}
thisstrokes.push(strokes[i].slice());
}
if (thisstrokes.length > 0){
thisstrokes = width_(thisstrokes.slice());
for (var j=0;j<thisstrokes.length;j++){
strokes2.push(thisstrokes[j].slice());
}
}
return strokes2;
}
function draw2(){
ctx2.clearRect(0, 0, w, h);
for (var s=-1;s<multistrokes.length;s++){
lc = -1;
llw = -1;
lsc = -1;
//strokes2 = strokeWidth(strokes.slice());
if (s==-1){
strokes2 = strokeWidth(strokes.slice());
}else{
strokes2 = strokeWidth(multistrokes[s].slice());
}
for (var i=0;i<strokes2.length;i++){
dx1 = strokes2[i][0];
dy1 = strokes2[i][1];
dx2 = strokes2[i][2];
dy2 = strokes2[i][3];
dc = strokes2[i][4];
lw = strokes2[i][5];
sc = strokes2[i][6];
r = strokes2[i][7];
g = strokes2[i][8];
b = strokes2[i][9];
if (document.getElementById('offsetly').checked){
ox = (dx2-dx1) * (Math.random()*0.4+0.8)/2.0;
oy = (dy2-dy1) * (Math.random()*0.4+0.8)/2.0;
cx = (dx2+dx1)/2.0;
cy = (dy2+dy1)/2.0;
dx1 = cx - ox;
dy1 = cy - oy;
dx2 = cx + ox;
dy2 = cy + oy;
}
//if ((lc != dc) || (llw != lw) ||) { //if it's the first stroke we set lx and ly to start there
if (lsc != sc) { //if different stroke count
lx = dx1;
ly = dy1;
lc = dc;
llw = lw;
lsc = sc;
}
if (Math.random()>=0.0) {
if (document.getElementById('offsetly').checked){
nx = dx2-dx1;
ny = dy2-dy1;
dx1 = lx;
dy1 = ly;
dx2 = lx+nx;
dy2 = ly+ny;
}
if (document.getElementById('stroketype').value == "1"){ //regular stroke
ctx2.beginPath();
ctx2.moveTo(dx1,dy1);
ctx2.lineTo(dx2,dy2);
//ctx2.strokeStyle = dc;
ctx2.strokeStyle = "rgb("+r+","+g+","+b+")";
ctx2.lineWidth = lw;
ctx2.stroke();
ctx2.closePath();
}else if (document.getElementById('stroketype').value == "2"){ //circles
ctx2.beginPath();
cx = (dx1+dx2)/2;
cy = (dy1+dy1)/2;
//ctx2.strokeStyle = dc;
ctx2.strokeStyle = "rgb("+r+","+g+","+b+")";
//ctx2.lineWidth = lw;
ctx2.lineWidth = Math.max(1.0,lw/10.0);
ctx2.arc(cx,cy,lw/2.0,0,Math.PI*2);
ctx2.stroke();
ctx2.closePath();
}
lx = dx2;
ly = dy2;
}
}
}
}
function draw1(){
ctx.clearRect(0, 0, w, h);
for (var i=0;i<strokes.length;i++){
dx1 = strokes[i][0];
dy1 = strokes[i][1];
dx2 = strokes[i][2];
dy2 = strokes[i][3];
dc = strokes[i][4];
lw = strokes[i][5];
sc = strokes[i][6];
ctx.beginPath();
ctx.moveTo(dx1,dy1);
ctx.lineTo(dx2,dy2);
ctx.strokeStyle = dc;
ctx.lineWidth = lw;
ctx.stroke();
ctx.closePath();
}
if (document.getElementById('reflect').checked){
for (var j=0;j<multistrokes.length;j++){
stroke = multistrokes[j];
for (var i=0;i<stroke.length;i++){
dx1 = stroke[i][0];
dy1 = stroke[i][1];
dx2 = stroke[i][2];
dy2 = stroke[i][3];
dc = stroke[i][4];
lw = stroke[i][5];
sc = stroke[i][6];
ctx.beginPath();
ctx.moveTo(dx1,dy1);
ctx.lineTo(dx2,dy2);
ctx.strokeStyle = dc;
ctx.lineWidth = lw;
ctx.stroke();
ctx.closePath();
}
}
}
// ctx.beginPath();
// ctx.moveTo(prevX, prevY);
// ctx.lineTo(currX, currY);
// ctx.strokeStyle = color;
// ctx.lineWidth = lineWidth;
// ctx.stroke();
// ctx.closePath();
}
function draw3(){
ctx3.globalAlpha = 1.0;
ctx3.clearRect(0,0,canvas3.width,canvas3.height);
//ctx3.fillStyle= 'white';
//ctx3.fillRect(0,0,canvas3.width,canvas3.height);
progression = 0;
by = parseInt(document.getElementById("byValue").value);
if (document.getElementById("grid").checked && document.getElementById("progression").checked){
progressions = by * by;
progression = 1;
p = []; //progressions
savedstrokes = strokes.slice();
for (var i=1;i<=progressions;i++){
p.push(strokes.slice(0,Math.round(strokes.length/progressions*i)));
}
}
for (var i=1;i<=8;i++){
if (document.getElementById("grid").checked){
size = canvas.width/by;
n = 0;
for (var y=0;y<by;y++){
for (var x=0;x<by;x++){
if (progression==1){
strokes = p[n].slice();
draw(0); //to calculate multi strokes
}
n+=1;
draw2();
ctx3.globalAlpha = 1.0/(i+1);
ctx3.drawImage(canvas2,x*size,y*size,size,size);
}
}
}else{
draw2();
ctx3.globalAlpha = 1.0/(i+1);
ctx3.drawImage(canvas2,0,0);
}
}
if (progression==1){
strokes = savedstrokes.slice();
}
}
function drawCursor(clear = 0){
if (clear == 1){
ctx.clearRect(0,0,canvas.width,canvas.height);
//redisplay them all before drawing cursor
//ctx.globalAlpha=1.0;
//ctx.drawImage(img,0,0,canvas.width,canvas.height);
draw1();
ctx.globalAlpha=.5;
ctx.drawImage(img,0,0,canvas.width,canvas.height);
ctx.globalAlpha=1.0;
}
ctx.beginPath();
ctx.arc(currX,currY,lineWidth/2.0,0,Math.PI*2.0);
saveLineWith = ctx.lineWidth;
ctx.lineWidth = 1;
savestrokeStyle = ctx.strokeStyle;
ctx.strokeStyle = 'red';
ctx.globalCompositeOperation = "xor";
ctx.stroke();
ctx.globalCompositeOperation = "source-over";
ctx.strokeStyle = savestrokeStyle;
ctx.lineWidth = saveLineWith;
}
mirrors = 6;
function reflectthem(mirrors){
mirrors = parseInt(mirrors);
reflection = [];
mx = canvas.width/2.0;
my = canvas.height/2.0;
for (var i=0;i<strokes.length;i++){
reflection.push(strokes[i].slice());
reflection[i][0] = mx - (reflection[i][0] - mx);
reflection[i][2] = mx - (reflection[i][2] - mx);
}
multistrokes.push(reflection);
incang = 360.0/mirrors/360.0*2*Math.PI;
for (var a=1;a<mirrors;a++){
ref = [];
for (var i=0;i<strokes.length;i++){
ref.push(strokes[i].slice());
p1angle = angleOf(mx,my,ref[i][0],ref[i][1]);
p2angle = angleOf(mx,my,ref[i][2],ref[i][3]);
p1radius = ((ref[i][0]-mx)**2+(ref[i][1]-my)**2)**0.5;
p2radius = ((ref[i][2]-mx)**2+(ref[i][3]-my)**2)**0.5;
newangle1 = p1angle+a*incang;
newangle2 = p2angle+a*incang;
ref[i][0] = mx + p1radius * Math.cos(newangle1);
ref[i][1] = my + p1radius * Math.sin(newangle1);
ref[i][2] = mx + p2radius * Math.cos(newangle2);
ref[i][3] = my + p2radius * Math.sin(newangle2);
}
multistrokes.push(ref);
ref = [];
for (var i=0;i<strokes.length;i++){
ref.push(reflection[i].slice());
p1angle = angleOf(mx,my,ref[i][0],ref[i][1]);
p2angle = angleOf(mx,my,ref[i][2],ref[i][3]);
p1radius = ((ref[i][0]-mx)**2+(ref[i][1]-my)**2)**0.5;
p2radius = ((ref[i][2]-mx)**2+(ref[i][3]-my)**2)**0.5;
newangle1 = p1angle+a*incang;
newangle2 = p2angle+a*incang;
ref[i][0] = mx + p1radius * Math.cos(newangle1);
ref[i][1] = my + p1radius * Math.sin(newangle1);
ref[i][2] = mx + p2radius * Math.cos(newangle2);
ref[i][3] = my + p2radius * Math.sin(newangle2);
}
multistrokes.push(ref);
}
}
function draw(add = 1) {
// ctx.beginPath();
// ctx.moveTo(prevX, prevY);
// ctx.lineTo(currX, currY);
// ctx.strokeStyle = color;
// ctx.lineWidth = lineWidth;
// ctx.stroke();
// ctx.closePath();
if (color.includes("rgb")){color = rgbStrToHex(color);
} //always turn it into hex
rgbthis = hexToRgb(color);
if (add == 1){
strokes.push([prevX,prevY,currX,currY,color,lineWidth,strokecount,rgbthis[0],rgbthis[1],rgbthis[2]]); // save stroke information as we draw
}
if (document.getElementById('reflect').checked){
multistrokes = [];
mirrors = parseInt(document.getElementById('mirrors').value);
reflectthem(mirrors);
}else{
multistrokes = [];
}
draw1();
drawCursor();
ctx.globalAlpha=.5;
ctx.drawImage(img,0,0,canvas.width,canvas.height);
ctx.globalAlpha=1.0;
draw2();
}
function erase() {
var m = confirm("Want to clear");
if (m) {
strokes = [];
strokecount = -1;
ctx.clearRect(0, 0, w, h);
ctx2.clearRect(0, 0, w, h);
document.getElementById("canvasimg").style.display = "none";
}
}
function save() {
document.getElementById("canvasimg").style.border = "2px solid";
var dataURL = canvas.toDataURL();
document.getElementById("canvasimg").src = dataURL;
document.getElementById("canvasimg").style.display = "inline";
}
// function getMousePos(canvas, evt) {
// var rect = canvas.getBoundingClientRect();
// return {
// x: evt.clientX - rect.left,
// y: evt.clientY - rect.top
// };
// }
function choosexy(res, e) {
rect = canvas1.getBoundingClientRect();
if (res == 'down') {
prevX = currX;
prevY = currY;
// currX = e.clientX - canvas1.offsetLeft;
// currY = e.clientY - canvas1.offsetTop;
currX = e.clientX - rect.left;
currY = e.clientY - rect.top;
if (currX < 640){
pixel = ctx1.getImageData(currX, currY, 1, 1).data;
color = "rgb("+pixel[0]+","+pixel[1]+","+pixel[2]+")";
}else{
lineWidth = (currX - 640)/120 * (60);
}
drawcolors();
}
}
function findxy(res, e) {
rect = canvas.getBoundingClientRect();
if (res == 'down') {
prevX = currX;
prevY = currY;
// currX = e.clientX - canvas.offsetLeft;
// currY = e.clientY - canvas.offsetTop;
currX = e.clientX - rect.left;
currY = e.clientY - rect.top;
flag = true;
dot_flag = true;
if (dot_flag) {
ctx.beginPath();
ctx.fillStyle = color;
ctx.fillRect(currX, currY, 2, 2);
ctx.closePath();
ctx2.beginPath();
ctx2.fillStyle = color;
ctx2.fillRect(currX, currY, 2, 2);
ctx2.closePath();
dot_flag = false;
}
}
if (res == 'up' || res == "out") {
flag = false;
strokecount += 1; //increment stroke count
}
if (res == 'move') {
if (flag) {
prevX = currX;
prevY = currY;
// currX = e.clientX - canvas.offsetLeft;
// currY = e.clientY - canvas.offsetTop;
currX = e.clientX - rect.left;
currY = e.clientY - rect.top;
draw();
}else{
// currX = e.clientX - canvas.offsetLeft;
// currY = e.clientY - canvas.offsetTop;
currX = e.clientX - rect.left;
currY = e.clientY - rect.top;
drawCursor(1);
}
}
}
function animate(){
if (document.getElementById('animate').checked){
draw2();
}
}
setInterval(animate,100);
function loadimage(){
image = document.getElementById("img");
image.onload = function(){
init();
}
image.src = document.getElementById('src').value;
}
function save(){
localStorage.setItem("tracer_strokes", JSON.stringify(strokes));
}
function load(){
strokes = JSON.parse(localStorage.getItem("tracer_strokes"));
}
draw();
</script>
<body onload="init()">
<canvas id="canvas" width="840" height="80" style="position:absolute;top:100px;left:0px;border:1px solid"></canvas>
<table><tr><td><img src='square.jpg' id='img' width="2000px" style="position:absolute;top:180px;left:0px;border:2px solid;"><canvas id="can" width="1200" height="1200" style="position:absolute;top:180px;left:0px;border:2px solid;"></canvas></td><td><canvas id="can2" width="1200" height="960" style="position:absolute;top:180px;left:1200px;border:2px solid;"></td>
<td><canvas id="can3" width="1200" height="960" style="position:absolute;top:180px;left:2400px;border:2px solid;"></td></tr></table><br/>
<div id='ph' style="position:absolute;top:2300px;left:0%;">
<input type='submit' value='Clear' onclick='erase()'><br/>
<input type='checkbox' id='offsetly' value=''>Offsetly Drawn<br/>
<!-- <input type='checkbox' id='shuffle' value=''>Shuffle Stroke Parts<br/> -->
<input type="checkbox" id='animate' checked>Continuous Redraws<br/>
<input type="checkbox" id='varycheckbox' checked>Vary Color Channels by <input type='text' id='varycolorby' value='50' size=3>/255 - <input type="checkbox" id='varywithinstroke'>Vary Within Strokes<br/>
Image location/url:<input type='text' id='src' value='seagull.jpg'><input type='submit' onclick='loadimage()' value='Load Image'><br/>
<select id="stroketype"><option value="1" selected>Regular Stroke</option>
<option value="2">Circles</option>
</select>
<input type='checkbox' id='reflect' checked>Reflect <input type='text' id='mirrors' value='6' size=3> Mirrors<br/>
<input type='checkbox' id='grid' checked>Grid (of Multiples) of <input type='text' id='byValue' value='4' size=3> n by n Value<br/>
<input type='checkbox' id='progression' checked>Show Progression (when in Grid mode)<br/>
<input type='submit' value='Redraw Canvas3' onclick='draw3()'><br/>
<br/>
<input type='submit' value='Save to Local Storage' onclick='save()'><input type='submit' value='Load from Local Storage' onclick='load()'><br/>
<div id='debug'></div>
<hr>
<div id='donate'>
The NSI (not so important) stuff: If you find this js/html useful, feel free to use it but if you make money from it (I ask that <br>
you transfer $1 USD per sale to me through Paypal at oldtran@gmail.com). If you don't use Paypal, then don't worry about it. I understand<br/>
that there might be fees so maybe save it until you have more than 10 sales then transfer to me once and minus the fee. I would appreciate<br/>
this and maybe even add features in the future to this existing program.<br/><br/>
I also ask that you donate $1 per sale to GIMP foundation.<br/><br/>
I think it's a fair deal, as there is no risk to you for using it for free as much as you please, and only turn around and donate only when you've made sales.<br/>
</div>
</div>
</body>
</html>