Skip to content

Commit d122ba6

Browse files
author
monkstone
committed
add a decent video capture example
1 parent 1b847f1 commit d122ba6

File tree

3 files changed

+107
-1
lines changed

3 files changed

+107
-1
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
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
Binary file not shown.

samples/processing_app/library/video/test_capture.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def setup
1111
p 'Matching cameras available:'
1212
size_pattern = Regexp.new(format('%dx%d', width, height))
1313
select = cameras.grep size_pattern # filter available cameras
14-
select.map { |cam| p cam }
14+
select.uniq.map { |cam| p cam.strip }
1515
fail 'There are no matching cameras.' if (select.length == 0)
1616
start_capture(select[0])
1717
end

0 commit comments

Comments
 (0)