From 78238ca84096c928d26ba887408a91fbeaa5dce8 Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Fri, 24 Dec 2010 17:10:15 +0000 Subject: adding camera blocks --- (limited to 'TurtleArt') diff --git a/TurtleArt/tacamera.py b/TurtleArt/tacamera.py new file mode 100644 index 0000000..f7e08ff --- /dev/null +++ b/TurtleArt/tacamera.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2010, Walter Bender +#Copyright (c) 2010, Tony Forster + +#Permission is hereby granted, free of charge, to any person obtaining a copy +#of this software and associated documentation files (the "Software"), to deal +#in the Software without restriction, including without limitation the rights +#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +#copies of the Software, and to permit persons to whom the Software is +#furnished to do so, subject to the following conditions: + +#The above copyright notice and this permission notice shall be included in +#all copies or substantial portions of the Software. + +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +#THE SOFTWARE. + +import gst, time + +def save_camera_input_to_file(imagepath): + """ Grab a frame from the video camera and save to a temporary file """ + + pipeline = gst.parse_launch( + 'v4l2src ! ffmpegcolorspace ! jpegenc ! filesink location=' + imagepath) + pipeline.set_state(gst.STATE_PLAYING) + + # Need to pause for pipeline to stablize + time.sleep(2) + + pipeline.set_state(gst.STATE_NULL) diff --git a/TurtleArt/taconstants.py b/TurtleArt/taconstants.py index 0ec31aa..4f45663 100644..100755 --- a/TurtleArt/taconstants.py +++ b/TurtleArt/taconstants.py @@ -136,8 +136,8 @@ PALETTES = [['clean', 'forward', 'back', 'show', 'left', 'right', 'myfunc1arg', 'userdefined', 'cartesian', 'width', 'height', 'polar', 'addturtle', 'reskin', 'sandwichtop_no_label', 'sandwichbottom'], - ['kbinput', 'keyboard', 'readpixel', 'see', 'sound', 'volume', - 'pitch'], + ['kbinput', 'keyboard', 'readpixel', 'see', 'readcamera', 'camera', + 'sound', 'volume', 'pitch'], ['journal', 'audio', 'video', 'description', 'hideblocks', 'showblocks', 'fullscreen', 'savepix', 'savesvg', 'mediawait', 'picturelist', 'picture1x1a', 'picture1x1', 'picture2x2', @@ -205,7 +205,7 @@ BASIC_STYLE = [] BASIC_STYLE_EXTENDED_VERTICAL = ['clean', 'penup', 'pendown', 'stack1', 'stack2', 'hideblocks', 'showblocks', 'clearheap', 'printheap', 'kbinput', 'fullscreen', 'cartesian', 'polar', 'startfill', 'mediawait', - 'stopfill', 'readpixel', 'vspace'] + 'stopfill', 'readpixel', 'readcamera', 'vspace'] INVISIBLE = ['sandwichcollapsed'] BASIC_STYLE_EXTENDED = ['picturelist', 'picture1x1', 'picture2x2', 'picture2x1', 'picture1x2', 'picture1x1a'] @@ -223,7 +223,7 @@ BOX_STYLE = ['number', 'xcor', 'ycor', 'heading', 'pensize', 'color', 'shade', 'red', 'orange', 'yellow', 'green', 'cyan', 'blue', 'purple', 'white', 'black', 'titlex', 'titley', 'leftx', 'topy', 'rightx', 'bottomy', 'sound', 'volume', 'pitch', 'voltage', 'resistance', 'gray', 'see', 'rfid'] -BOX_STYLE_MEDIA = ['description', 'audio', 'journal', 'video'] +BOX_STYLE_MEDIA = ['description', 'audio', 'journal', 'video', 'camera'] NUMBER_STYLE = ['plus2', 'product2', 'myfunc'] NUMBER_STYLE_VAR_ARG = ['myfunc1arg', 'myfunc2arg', 'myfunc3arg'] NUMBER_STYLE_BLOCK = ['random'] @@ -277,7 +277,7 @@ OLD_DOCK = ['and', 'or', 'plus', 'minus', 'division', 'product', 'remainder'] # Blocks that contain media # CONTENT_BLOCKS = ['number', 'string', 'description', 'audio', 'video', - 'journal'] + 'journal', 'camera'] # # These blocks get a special skin @@ -313,6 +313,7 @@ BLOCK_NAMES = { 'box': [_('box')], 'box1': [_('box 1')], 'box2': [_('box 2')], + 'camera': [' '], 'cartesian': [_('Cartesian')], 'clean': [_(' clean ')], 'clearheap': [_('empty heap')], @@ -385,6 +386,7 @@ BLOCK_NAMES = { 'purple': [_('purple')], 'push': [_('push')], 'random': [_('random'), _('min'), _('max')], + 'readcamera': [_('read camera')], 'readpixel': [_('read pixel')], 'red': [_('red')], 'remainder2': [_('mod')], @@ -540,6 +542,7 @@ PRIMITIVES = { 'push': 'push', 'random': 'random', 'red': 'red', + 'readcamera': 'readcamera', 'readpixel': 'readpixel', 'remainder2': 'mod', 'repeat': 'repeat', @@ -621,6 +624,7 @@ DEFAULTS = { 'audio': [None], 'back': [100], 'box': [_('my box')], + 'camera': ['CAMERA'], 'comment': [_('comment')], 'description': [None], 'fillscreen': [60, 80], @@ -696,6 +700,7 @@ CONTENT_ARGS = ['show', 'showaligned', 'push', 'storein', 'storeinbox1', MEDIA_SHAPES = ['audiooff', 'audioon', 'audiosmall', 'videooff', 'videoon', 'videosmall', + 'cameraoff', 'camerasmall', 'journaloff', 'journalon', 'journalsmall', 'descriptionoff', 'descriptionon', 'descriptionsmall', 'pythonoff', 'pythonon', 'pythonsmall', @@ -751,6 +756,7 @@ TEMPLATES = {'t1x1': (0.5, 0.5, 0.0625, 0.125, 1.05, 0), # SPECIAL_NAMES = { 'audio': _('audio'), + 'camera': _('camera'), 'division2': _('divide'), 'equal2': _('equal'), 'greater2': _('greater than'), @@ -790,6 +796,7 @@ HELP_STRINGS = { 'box1': _("Variable 1 (numeric value)"), 'box2': _("Variable 2 (numeric value)"), 'box': _("named variable (numeric value)"), + 'camera': _('camera output'), 'cartesian': _("displays Cartesian coordinates"), 'clean': _("clears the screen and reset the turtle"), 'clearheap': _("emptys FILO (first-in-last-out heap)"), @@ -860,6 +867,7 @@ HELP_STRINGS = { 'product2': _("multiplies two numeric inputs"), 'push': _("pushes value onto FILO (first-in last-out heap)"), 'random': _("returns random number between minimum (top) and maximum (bottom) values"), + 'readcamera': _("Average RGB color from camera is pushed to the stack"), 'readpixel': _("RGB color under the turtle is pushed to the stack"), 'remainder2': _("modular (remainder) operator"), 'repeat': _("loops specified number of times"), diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py index bab3b0a..2da8685 100755 --- a/TurtleArt/talogo.py +++ b/TurtleArt/talogo.py @@ -44,9 +44,10 @@ from taconstants import TAB_LAYER, BLACK, WHITE, \ SENSOR_DC_BIAS, XO1, XO15 from tagplay import play_audio_from_file, play_movie_from_file, stop_media, \ media_playing +from tacamera import save_camera_input_to_file from tajail import myfunc, myfunc_import from tautils import get_pixbuf_from_journal, convert, data_from_file, \ - text_media_type, round_int, chr_to_ord, strtype + text_media_type, round_int, chr_to_ord, strtype, get_path from RtfParser import RtfTextOnly @@ -401,6 +402,7 @@ class LogoCode: 'purple': [0, lambda self: CONSTANTS['purple']], 'push': [1, lambda self, x: self._prim_push(x)], 'random': [2, lambda self, x, y: _random(x, y)], + 'readcamera': [0, lambda self: self._read_camera()], 'readpixel': [0, lambda self: self._read_pixel()], 'red': [0, lambda self: CONSTANTS['red']], 'repeat': [2, self._prim_repeat, True], @@ -527,6 +529,12 @@ class LogoCode: self.voltage_gain = -0.0001471 self.voltage_bias = 1.695 + if self.tw.running_sugar: + self.imagepath = get_path(self.tw.activity, + 'data/turtlepic.jpg') + else: + self.imagepath = '/tmp/turtlepic.jpg' + def _def_prim(self, name, args, fcn, rprim=False): """ Define the primitives associated with the blocks """ sym = self._intern(name) @@ -628,6 +636,8 @@ class LogoCode: code.append('#svideo_' + str(blk.values[0])) else: code.append('#svideo_None') + elif blk.name == 'camera': + code.append('#smedia_CAMERA') else: return ['%nothing%'] else: @@ -1303,7 +1313,6 @@ class LogoCode: def _show(self, string, center=False): """ Show is the general-purpose media-rendering block. """ - # convert from Turtle coordinates to screen coordinates if type(string) == str or type(string) == unicode: if string in ['media_', 'descr_', 'audio_', 'video_', 'media_None', 'descr_None', 'audio_None', @@ -1312,7 +1321,10 @@ class LogoCode: elif string[0:6] in ['media_', 'descr_', 'audio_', 'video_']: self.filepath = None dsobject = None - if os.path.exists(string[6:]): # is it a path? + if string[6:] == 'CAMERA': + save_camera_input_to_file(self.imagepath) + self.filepath = self.imagepath + elif os.path.exists(string[6:]): # is it a path? self.filepath = string[6:] elif self.tw.running_sugar: # is it a datastore object? try: @@ -1449,6 +1461,34 @@ class LogoCode: self.heap.append(g) self.heap.append(r) + def _read_camera(self): + """ Read average pixel from camera and push b, g, r to the stack """ + save_camera_input_to_file(self.imagepath) + pixbuf = None + w = self._w() + h = self._h() + if w < 1 or h < 1: + return + pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.imagepath, w, h) + + array = pixbuf.get_pixels() + length = len(array) / 3 + r = 0 + g = 0 + b = 0 + i = 0 + if array is not None: + for j in range(length): + r += ord(array[i]) + i += 1 + g += ord(array[i]) + i += 1 + b += ord(array[i]) + i += 1 + self.heap.append(int((b / length))) + self.heap.append(int((g / length))) + self.heap.append(int((r / length))) + def _get_volume(self): """ return mic in value """ #TODO: Adjust gain for different HW diff --git a/TurtleArt/tawindow.py b/TurtleArt/tawindow.py index b67dee5..ceb9a69 100644..100755 --- a/TurtleArt/tawindow.py +++ b/TurtleArt/tawindow.py @@ -1572,7 +1572,7 @@ class TurtleArtWindow(): self.saved_string = blk.spr.labels[0] blk.spr.labels[0] += CURSOR - elif blk.name in BOX_STYLE_MEDIA: + elif blk.name in BOX_STYLE_MEDIA and blk.name != 'camera': self._import_from_journal(self.selected_blk) if blk.name == 'journal' and self.running_sugar: self._load_description_block(blk) @@ -2504,7 +2504,7 @@ class TurtleArtWindow(): self._block_skin('pythonoff', blk) elif btype in BOX_STYLE_MEDIA and blk.spr is not None: if len(blk.values) == 0 or blk.values[0] == 'None' or \ - blk.values[0] is None: + blk.values[0] is None or btype == 'camera': self._block_skin(btype + 'off', blk) elif btype == 'video' or btype == 'audio' or \ btype == 'description': -- cgit v0.9.1