# HG changeset patch # User Drew Perttula # Date 2017-04-15 19:16:32 # Node ID 69088fe2865e7f2a39e16647e3b22403cf5ea910 # Parent 15f296550447002a653298c058d2ddcac22f2aea more progress on paint Ignore-this: ff24e7a8e8f95bde364841c6076e839 diff --git a/bin/paintserver b/bin/paintserver --- a/bin/paintserver +++ b/bin/paintserver @@ -15,12 +15,15 @@ from light9.rdfdb import clientsession import light9.paint.solve from lib.cycloneerr import PrettyErrorHandler + class Solve(PrettyErrorHandler, cyclone.web.RequestHandler): def post(self): painting = json.loads(self.request.body) reload(light9.paint.solve) + solver = light9.paint.solve.Solver(self.settings.graph) + solver.loadSamples() with self.settings.stats.solve.time(): - out = light9.paint.solve.solve(painting) + out = solver.solve(painting) self.write(json.dumps(out)) class App(object): diff --git a/light9/paint/solve.py b/light9/paint/solve.py --- a/light9/paint/solve.py +++ b/light9/paint/solve.py @@ -1,2 +1,47 @@ -def solve(painting): - return 0 +from light9.namespaces import RDF, L9 +from PIL import Image +import scipy.misc +import cairo + +class Solver(object): + def __init__(self, graph): + self.graph = graph + self.samples = {} # uri: Image array + + def loadSamples(self): + """learn what lights do from images""" + + with self.graph.currentState() as g: + for samp in g.subjects(RDF.type, L9['LightSample']): + path = 'show/dance2017/cam/test/%s' % g.value(samp, L9['path']) + img = Image.open(path) + img.thumbnail((100, 100)) + self.samples[samp] = scipy.misc.fromimage(img, mode='RGB') + + def draw(self, painting, w, h): + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) + ctx = cairo.Context(surface) + ctx.move_to(0, 0) + ctx.line_to(100,30) + + ctx.set_source_rgb(0.3, 0.2, 0.5) + ctx.set_line_width(20) + ctx.stroke() + # then blur? + surface.write_to_png('/tmp/surf.png') + + def solve(self, painting): + """ + given strokes of colors on a photo of the stage, figure out the + best light settings to match the image + """ + self.draw(painting, 100, 80) + return 0 + + + def simulationLayers(self, settings): + """ + how should a simulation preview approximate the light settings + (device attribute values) by combining photos we have? + """ + diff --git a/light9/paint/solve_test.py b/light9/paint/solve_test.py new file mode 100644 --- /dev/null +++ b/light9/paint/solve_test.py @@ -0,0 +1,12 @@ +import unittest +import solve + +class TestSolve(unittest.TestCase): + def testBlack(self): + s = solve.Solver() + s.loadSamples() + devAttrs = s.solve({'strokes': []}) + self.assertEqual([], devAttrs) + + + diff --git a/light9/web/paint/bg2.jpg b/light9/web/paint/bg2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e695c87cfd03c77e7afa463413f383d0a1024990 GIT binary patch literal 18998 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 + @strokes = [] + + addStroke: (pts, color) -> + @strokes.push({pts: pts, color: color}) + + getDoc: -> + {strokes: @strokes} + class Stroke - constructor: (pos) -> + constructor: (pos, @color) -> @path = document.createElementNS('http://www.w3.org/2000/svg', 'path') @path.setAttributeNS(null, 'd', "M #{pos[0]} #{pos[1]}") + @pts = [pos] @lastPos = pos appendElem: (parent) -> @@ -11,6 +22,7 @@ class Stroke if Math.hypot(pos[0] - @lastPos[0], pos[1] - @lastPos[1]) < 30 return @path.attributes.d.value += " L #{pos[0]} #{pos[1]}" + @pts.push(pos) @lastPos = pos Polymer @@ -20,6 +32,7 @@ Polymer properties: { } ready: -> + @painting = new Painting() @$.paint.addEventListener('mousedown', @onDown.bind(@)) @$.paint.addEventListener('mousemove', @onMove.bind(@)) @$.paint.addEventListener('mouseup', @onUp.bind(@)) @@ -28,11 +41,12 @@ Polymer @$.paint.addEventListener('touchend', @onUp.bind(@)) evPos: (ev) -> - return (if ev.touches?.length? then [Math.round(ev.touches[0].clientX), Math.round(ev.touches[0].clientY)] else [ev.x, ev.y]) + return (if ev.touches?.length? then [Math.round(ev.touches[0].clientX), + Math.round(ev.touches[0].clientY)] else [ev.x, ev.y]) onDown: (ev) -> # if it's on an existing one, do selection - @stroke = new Stroke(@evPos(ev)) + @stroke = new Stroke(@evPos(ev), '#aaaaaa') @stroke.appendElem(@$.paint) @scopeSubtree(@$.paint) @@ -42,6 +56,9 @@ Polymer @stroke.move(@evPos(ev)) onUp: (ev) -> + @painting.addStroke(@stroke.pts, @stroke.color) + @$.solve.body = JSON.stringify(@painting.getDoc()) + @$.solve.generateRequest() @stroke = null onResize: (ev) -> diff --git a/light9/web/paint/paint-elements.html b/light9/web/paint/paint-elements.html --- a/light9/web/paint/paint-elements.html +++ b/light9/web/paint/paint-elements.html @@ -1,5 +1,6 @@ +