// Program to simulate cross-stitch. // Draws a single "x" in a cross-stitch. drawX[gr is graphics, left, top, right, bottom, r, g, b, sdColor, threadWidth, subThreads, jitter] := { width = right-left height = bottom-top halfWidth = width / 2 halfHeight = height / 2 perSide = sqrt[subThreads] // Width of each sub-thread subWidth = threadWidth / perSide * 1.1 // TODO: Make this changeable halfThreadWidth = threadWidth / 2 quarterThreadWidth = threadWidth / 4 xc1 = left + halfThreadWidth yc1 = top + halfThreadWidth xc2 = right - halfThreadWidth yc2 = bottom - halfThreadWidth halfThreadWidth = threadWidth / 2 gr.stroke[subWidth] gr.color[.5,.5,.5] gr.fillEllipseCenter[right,bottom,threadWidth,threadWidth] for n = 0 to subThreads-1 { xx = (n mod perSide) / perSide yy = (n div perSide) / perSide xo = threadWidth * xx - halfThreadWidth yo = threadWidth * yy - halfThreadWidth jitterWidth = subWidth * jitter gr.color[randColor[r, sdColor], randColor[g, sdColor], randColor[b, sdColor], .5] gr.line[randomGaussian[xc1 + xo, jitterWidth], randomGaussian[yc1 + yo, jitterWidth], randomGaussian[xc2 + xo, jitterWidth], randomGaussian[yc2 + yo, jitterWidth]] gr.color[randColor[r, sdColor], randColor[g, sdColor], randColor[b, sdColor], .5] gr.line[randomGaussian[xc1 + xo, jitterWidth], randomGaussian[yc2 + yo, jitterWidth], randomGaussian[xc2 + xo, jitterWidth], randomGaussian[yc1 + yo, jitterWidth]] } } // Picks a normally-distributed color component around the color component x // with specified standard deviation. randColor[x, sd] := constrain[randomGaussian[x, sd], 0, 1] // Constrains the value of x to be between min and max. constrain[x, min, max] := (x < min ? min : (x > max ? max : x)) // Draw a cross-stitch of the image. crossStitchImage[gr is graphics, i, left, top, right, bottom, steps] := { w = i.getWidth[] h = i.getHeight[] aspect = w/h if (aspect > 1) // Wider than tall? { xstep = w/round[steps*aspect] ystep = h/steps } else { xstep = w / steps ystep = h / round[steps/aspect] } threadWidth = .3 xstep for x=0 to w-xstep step xstep for y = 0 to h-ystep step ystep { [r,g,b,a] = i.averagePixels[x,y,x+xstep, y+ystep] drawX[gr,x,y,x+xstep,y+ystep,r,g,b,.15,threadWidth,36,.7] } } g = new graphics g.backgroundColor[0.7,0.7,0.7] //i = new image["http://futureboy.us/images/futureboydomethumb4.gif"] //i = new image["file:maui.jpg"] //i = new image["file:kittyface.jpg"] i = new image["file:jeffreycrop.jpg"] crossStitchImage[g, i, 0, 0, 1, 1, 40] g.show[] g.write["jeffreycrop.html",1000,800] browse["jeffreycrop.html"] g.write["jeffreycrop.svg",1000,800]