|
| 1 | +# |
| 2 | +# ASCII Video |
| 3 | +# by Ben Fry, translated to ruby-processing by Martin Prout. |
| 4 | +# |
| 5 | +# |
| 6 | +# Text characters have been used to represent images since the earliest computers. |
| 7 | +# This sketch is a simple homage that re-interprets live video as ASCII text. |
| 8 | +# See the key_pressed function for more options, like changing the font size. |
| 9 | +# |
| 10 | +load_library :video |
| 11 | +include_package 'processing.video' |
| 12 | + |
| 13 | +attr_reader :bright, :char, :cheat_screen, :font, :font_size, :letters, :video |
| 14 | + |
| 15 | +# All ASCII characters, sorted according to their visual density |
| 16 | +LETTER_STRING = %q{ .`-_':,;^=+/\"|)\\<>)iv%xclrs{*}I?!][1taeo7zjLunT#JCwfy325Fp6mqSghVd4EgXPGZbYkOA&8U$@KHDBWNMR0Q} |
| 17 | +LETTER_ORDER = LETTER_STRING.scan(/./) |
| 18 | +def setup |
| 19 | + size(640, 480) |
| 20 | + # This the default video input, see the GettingStartedCapture |
| 21 | + # example if it creates an error |
| 22 | + @video = Capture.new(self, 160, 120) |
| 23 | + # @cheat_screen = true |
| 24 | + # Start capturing the images from the camera |
| 25 | + video.start |
| 26 | + @font_size = 1.5 |
| 27 | + @font = load_font(data_path('UniversLTStd-Light-48.vlw')) |
| 28 | + # for the 256 levels of brightness, distribute the letters across |
| 29 | + # the an array of 256 elements to use for the lookup |
| 30 | + @letters = (0...256).map do |i| |
| 31 | + LETTER_ORDER[map1d(i, (0...256), (0...LETTER_ORDER.length))] |
| 32 | + end |
| 33 | + # current brightness for each point |
| 34 | + @bright = Array.new(video.width * video.height, 128) |
| 35 | +end |
| 36 | + |
| 37 | +def capture_event(c) |
| 38 | + c.read |
| 39 | + background 0 |
| 40 | +end |
| 41 | + |
| 42 | +def draw |
| 43 | + return unless (video.available == true) |
| 44 | + capture_event(video) |
| 45 | + push_matrix |
| 46 | + hgap = width / video.width |
| 47 | + vgap = height / video.height |
| 48 | + scale([hgap, vgap].max * font_size) |
| 49 | + text_font(font, font_size) |
| 50 | + index = 0 |
| 51 | + video.load_pixels |
| 52 | + (0...video.height).each do |
| 53 | + # Move down for next line |
| 54 | + translate(0, 1.0 / font_size) |
| 55 | + push_matrix |
| 56 | + (0...video.width).each do |
| 57 | + pixel_color = video.pixels[index] |
| 58 | + # Faster method of calculating r, g, b than red(), green(), blue() |
| 59 | + r = pixel_color >> 16 & 0xff |
| 60 | + g = pixel_color >> 8 & 0xff |
| 61 | + b = pixel_color & 0xff |
| 62 | + # Another option would be to properly calculate brightness as luminance: |
| 63 | + # luminance = 0.3*red + 0.59*green + 0.11*blue |
| 64 | + # Or you could instead red + green + blue, and make the the values[] array |
| 65 | + # 256*3 elements long instead of just 256. |
| 66 | + pixel_bright = [r, g, b].max |
| 67 | + # The 0.1 value is used to damp the changes so that letters flicker less |
| 68 | + diff = pixel_bright - bright[index] |
| 69 | + bright[index] += diff * 0.1 |
| 70 | + fill(pixel_color) |
| 71 | + text(letters[bright[index]], 0, 0) |
| 72 | + # Move to the next pixel |
| 73 | + index += 1 |
| 74 | + # Move over for next character |
| 75 | + translate(1.0 / font_size, 0) |
| 76 | + end |
| 77 | + pop_matrix |
| 78 | + end |
| 79 | + pop_matrix |
| 80 | + if cheat_screen |
| 81 | + # image(video, 0, height - video.height) |
| 82 | + # set() is faster than image() when drawing untransformed images |
| 83 | + set(0, height, video) |
| 84 | + end |
| 85 | +end |
| 86 | + |
| 87 | +# |
| 88 | +# Handle key presses: |
| 89 | +# 'c' toggles the cheat screen that shows the original image in the corner |
| 90 | +# 'g' grabs an image and saves the frame to a tiff image |
| 91 | +# 'f' and 'F' increase and decrease the font size |
| 92 | +# |
| 93 | +def key_pressed |
| 94 | + case key |
| 95 | + when 'g' |
| 96 | + save_frame |
| 97 | + when 'c' |
| 98 | + @cheat_screen = !cheat_screen |
| 99 | + when 'f' |
| 100 | + @font_size *= 1.1 |
| 101 | + when 'F' |
| 102 | + @font_size *= 0.9 |
| 103 | + else |
| 104 | + p 'Controls are g to save_frame, f & F to set font size' |
| 105 | + end |
| 106 | +end |
0 commit comments