diff --git a/conf.json b/conf.json
index 383c89db8d0c2dbc19c09d424cba245dfbe4c9ec..2872a9af32bbdc21506692ae9cd92891e109ddd2 100644
--- a/conf.json
+++ b/conf.json
@@ -8,6 +8,8 @@
     "bins":19,
     "removed_top_bins":3,
     "pitch_min":0,
-    "pitch_step":1
+    "pitch_step":1,
+    "height_scale":5,
+    "width_scale" :0.5
 }
  
diff --git a/linescan.py b/linescan.py
index 707d0c0a1e9271050f37bf65763bb6c165807276..68e50af5ba0f1438c7702d27e43d7407534f0c09 100755
--- a/linescan.py
+++ b/linescan.py
@@ -29,6 +29,9 @@ else:
   camera.exposure_mode='off'
   camera.shutter_speed=conf["shutter_milliseconds"]*1000
   rawCapture = PiRGBArray(camera, size=tuple(conf["resolution"]))
+  # allow the camera to warmup
+  print("[INFO] warming up...")
+  time.sleep(conf["camera_warmup_time"])
 
 
 # we are a Jack MIDI jack_client to send MIDI messages
@@ -44,11 +47,6 @@ def process(frames):
     midi_outport.write_midi_event(0,midi_output_queue.pop())
 jack_client.activate()
 
-# allow the camera to warmup
-print("[INFO] warming up...")
-time.sleep(conf["camera_warmup_time"])
-
-pixel_count=0
 
 histogram_steps=conf["bins"]
 threshold=conf["threshold"]
@@ -70,6 +68,8 @@ while True:
     # cropped_frame=frame[100:280,0:640]
     cropped_frame=frame[0:480,0:640]
 
+
+    # histogram output
     # crop single line for color histogram output
     line_frame=cropped_frame[140:141,5:635]
     # compute b/w histogram
@@ -77,11 +77,9 @@ while True:
     histogram=np.zeros(histogram_steps,dtype=np.uint16)
     for pixel in np.nditer(line_frame):
         histogram[(int)(pixel*histogram_steps/256)]+=1
-
+    # send histogram as MIDI CC messages
     index=1
-
     for pixel in np.nditer(histogram[0:-conf['removed_top_bins']]):
-
         velocity=pixel-threshold
         if velocity>127:
             velocity=127
@@ -89,12 +87,45 @@ while True:
             velocity=0
         packet=((0xB<<4), index, velocity) # MIDI CC ("Continuous Controller") message
         midi_output_queue.append(packet)
-
         index+=1
     
-    cv2.imshow("Security Feed", cropped_frame)
-    #cv2.imshow("Security Feed 2", histogram)
+    # shape output
+    # gather depth data from a laser line projection
+    gray=cv2.cvtColor(cropped_frame, cv2.COLOR_BGR2GRAY)
+    grad_y = cv2.Sobel(gray, cv2.CV_8U, 0, 2, ksize=5, scale=-.1, delta=0, borderType=cv2.BORDER_DEFAULT)
+    _, laser = cv2.threshold(grad_y, 165, 255, cv2.THRESH_BINARY)
+    weights=np.arange(laser.shape[0],dtype=float)
+    laser[0:400][0:640]=0
+    laser[478:480][0:640]=0
+
+    weighted=np.tensordot(laser,weights,[[0],[0]])
+    count   =np.sum      (laser.astype(float),0)
+    depths  =weighted / count
+    
+    depths=depths[count>0] # cut NaN's
+    
+    # cut floor (small percentile)
+    baseline=np.percentile(depths,95)
+    depths=depths[depths<baseline-2]
+    
+    depth_min   =np.min(depths)
+    depth_mean  =np.mean(depths)
+    depth_width =np.sum(depths>0)
+    depth_height=baseline-depth_mean
+    
+    print("baseline "+str(baseline)+" min "+str(depth_min)+" mean "+str(depth_mean)+" width "+str(depth_width)+" height "+str(depth_height))
+
+    # send out mean width and height of the scanned pieces by MIDI CC 64 and 65.
+    midi_output_queue.append(((0xB<<4), 64, int(depth_height*conf['height_scale'])))
+    midi_output_queue.append(((0xB<<4), 65, int(depth_width *conf['width_scale' ])))
 
+    # impaint max to laser image (preview)
+    laser[int(baseline+1)][:]=100
+    laser[int(depth_min)][:]=100
+
+    cv2.imshow("Security Feed", cropped_frame)
+    cv2.imshow("laser", laser)
+    
     # if the `q` key is pressed, break from the lop
     key = cv2.waitKey(1) & 0xFF
     if key == ord("q"):