-
Notifications
You must be signed in to change notification settings - Fork 0
/
voyeur_activity.rb
288 lines (262 loc) · 9.26 KB
/
voyeur_activity.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# This file is part of com.andredlight.voyeur.
#
# com.andredlight.voyeur is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# com.andredlight.voyeur is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with com.andredlight.voyeur. If not, see <http://www.gnu.org/licenses/>.
require 'ruboto/activity'
require 'ruboto/widget'
require 'ruboto/util/stack'
require 'ruboto/util/toast'
require 'ruboto/generate'
ruboto_import_widgets :TextView, :LinearLayout, :Button
java_import 'android.app.Activity'
java_import 'android.content.Intent'
java_import 'android.content.pm.ActivityInfo'
java_import 'android.os.Bundle'
java_import 'android.util.Log'
java_import 'android.view.View'
java_import 'android.widget.ImageView'
java_import 'android.provider.MediaStore'
java_import 'java.io.File' do |package_name, class_name|
class_name = "JFile"
end
java_import 'java.io.FileOutputStream'
java_import 'java.io.FileNotFoundException'
java_import 'android.net.Uri'
java_import 'android.graphics.BitmapFactory'
java_import 'android.graphics.Bitmap'
java_import 'android.media.FaceDetector'
java_import 'android.graphics.Canvas'
java_import 'android.graphics.Color'
java_import 'android.graphics.Paint'
java_import 'android.graphics.PointF'
java_import 'android.graphics.Rect'
java_import 'android.view.SurfaceHolder'
java_import 'android.view.SurfaceView'
java_import 'android.view.Window'
java_import 'android.os.Debug'
ruboto_import_widget :SurfaceView, "android.view"
module SurfaceDraw
def draw_on_surface(holder, point, color)
setup_draw(holder)
@canvas.drawCircle(point[0], point[1], 5.0, color)
end_draw
end
def setup_draw(holder=nil)
Log.i("VOYEUR", "setup_draw called with holder: #{holder}")
@holder = holder if holder
@surface = @holder.getSurface
Log.i("VOYEUR", "surface was #{@surface.inspect}")
@surface_frame = @holder.getSurfaceFrame
save_file = "/sdcard/123save.jpg"
if File.exists?(save_file)
use_this_file = save_file
else
use_this_file = "/sdcard/123.jpg"
end
@mBitmap ||= BitmapFactory.decodeFile(use_this_file)
@viewWidth = @surface_frame.width
@viewHeight = @surface_frame.height
@drawing_cache_bitmap ||= Bitmap.createBitmap(@viewWidth, @viewHeight, Bitmap::Config::ARGB_8888)
@alt_canvas ||= Canvas.new(@drawing_cache_bitmap)
@holder.synchronized do
@canvas = @holder.lockCanvas(nil)
end
end
def init_drawing(holder=nil)
@holder = holder if holder
setup_draw(@holder)
@alt_canvas.drawBitmap(@mBitmap, nil, Rect.new(0,0, @viewWidth, @viewHeight), @tmpPaint)
flush_to_canvas
end_draw
end
def undo_all
@mBitmap.recycle
@mBitmap = nil
init_drawing
end
def flush_to_canvas
@canvas.drawBitmap(@drawing_cache_bitmap, nil, Rect.new(0,0, @viewWidth, @viewHeight), @tmpPaint)
end
def end_draw
@surface.unlockCanvasAndPost(@canvas)
end
def draw_over_faces
setup_draw
num_faces = 1
getAllFaces = FaceDetector::Face[num_faces].new
eyesMidPts = Array.new
eyesDistance = Array.new
picWidth = @mBitmap.getWidth.to_f
picHeight = @mBitmap.getHeight.to_f
viewWidth = @surface_frame.width
viewHeight = @surface_frame.height
xRatio = viewWidth / picWidth
yRatio = viewHeight / picHeight
arrayFaces = FaceDetector.new( picWidth, picHeight, num_faces )
arrayFaces.findFaces(@mBitmap, getAllFaces)
eyesMP = PointF.new
the_eyes = Array.new
getAllFaces.each do |face|
Log.i("VOYEUR", "begin face detection")
if face != nil
Log.i("VOYEUR", "found a face!")
@found_faces = true
face.getMidPoint(eyesMP)
the_eyes << {:midpoint => eyesMP, :eye_distance => face.eyesDistance}
end
end
tmpPaint = Paint.new(Paint::ANTI_ALIAS_FLAG)
tmpPaint.setStyle(Paint::Style::STROKE)
tmpPaint.setTextAlign(Paint::Align::CENTER)
color = Paint.new(Paint::ANTI_ALIAS_FLAG)
color.setStyle(Paint::Style::FILL)
color.setColor(Color::GRAY)
the_eyes.each do |face|
@alt_canvas.drawCircle(face[:midpoint].x * xRatio, face[:midpoint].y * yRatio, face[:eye_distance].to_f * xRatio, color);
end
flush_to_canvas
end_draw
@found_faces
end
def recycle
@mBitmap.recycle
@drawing_cache_bitmap.recycle
end
end
# The callbacks for the Edit View
class RubotoSurfaceHolderCallback
include SurfaceDraw
def set_touch_listener(tl)
@touch_listener = tl
end
def surfaceCreated(holder)
Log.i("VOYEUR", "surfaceCreate called")
# use the touch_listener to initialize the drawing surface
@touch_listener.init_drawing(holder)
true
end
def surfaceChanged(holder, format, width, height)
Log.i("VOYEUR", "surfaceChanged called")
end
def surfaceDestroyed(holder)
Log.i("VOYEUR", "surfaceDestroyed called")
@touch_listener.recycle
#Debug.stopAllocCounting
#Debug.stopMethodTracing
end
end
class OnTouchListener
include SurfaceDraw
attr_accessor :drawing_cache_bitmap
def onTouch(view, event)
Log.i("VOYEUR", "onTouch called")
x = event.getX
y = event.getY
point = [x,y]
color = Paint.new(Paint::ANTI_ALIAS_FLAG)
color.setStyle(Paint::Style::FILL)
color.setColor(Color::GRAY)
setup_draw(view.getHolder)
@alt_canvas.drawCircle(point[0], point[1], 7.0, color)
@tmpPaint ||= Paint.new(Paint::ANTI_ALIAS_FLAG)
@tmpPaint.setStyle(Paint::Style::STROKE)
@tmpPaint.setTextAlign(Paint::Align::CENTER)
flush_to_canvas
end_draw
Log.i("VOYEUR", "onTouch draw complete")
true
end
end
class RubotoActivity
def self.edit(context)
context.start_ruboto_activity("$activity_edit") do
def on_create(bundle)
# due to bug in ruboto activity or something this doesn't work.
# TODO: would like to fix orientation problem in Edit Activity
#if self.getRequestedOrientation == ActivityInfo::SCREEN_ORIENTATION_UNSPECIFIED
# self.setRequestedOrientation(ActivityInfo::SCREEN_ORIENTATION_PORTRAIT)
#else
# self.setRequestedOrientation(self.getRequestedOrientation)
#end
setTitle 'Edit'
Log.i("VOYEUR", "EDIT ACTIVITY STARTING")
setContentView(linear_layout(:orientation => :vertical) do
linear_layout do
#button :text => "Menu", :on_click_listener => @handle_click_menu
button :text => "Undo All", :on_click_listener => @handle_click_undo
button :text => "Save", :on_click_listener => @handle_click_save
button :text => "Face", :on_click_listener => @handle_click_face
end
@sv = surface_view
@callback ||= RubotoSurfaceHolderCallback.new
@touch_listener ||= OnTouchListener.new
@callback.set_touch_listener(@touch_listener)
@sv.holder.add_callback @callback
@sv.setOnTouchListener @touch_listener
end)
end
@handle_click_save = proc do |view|
savefile = JFile.new("/sdcard/123save.jpg")
outStream = FileOutputStream.new(savefile)
@touch_listener.drawing_cache_bitmap.compress(Bitmap::CompressFormat::JPEG, 100, outStream);
outStream.flush
outStream.close
toast "saved."
end
# This caused bug in orientation stuff.
#@handle_click_menu = proc do |view|
# #self.setRequestedOrientation(ActivityInfo::SCREEN_ORIENTATION_USER)
# RubotoActivity.launch(self)
#end
@handle_click_face = proc do |view|
unless @touch_listener.draw_over_faces
toast "no face detected."
end
end
@handle_click_undo = proc do |view|
del_this = JFile.new("/sdcard/123save.jpg")
del_this.delete
@touch_listener.undo_all
#RubotoActivity.launch(self)
end
end
end
def self.launch(context)
context.start_ruboto_activity("$activity_voyeur") do
def on_create(bundle)
#Debug.startMethodTracing("voyeurtrace")
#Debug.startAllocCounting
setTitle 'Voyeur'
setContentView(
linear_layout(:orientation => :vertical) do
@text_view = text_view :text => "an AndRedLight Production"
button :text => "Capture Pic", :width => :fill_parent, :on_click_listener => @on_capture_click
button :text => "Edit Pic", :width => :fill_parent, :on_click_listener => @on_edit_click
end
)
end
def on_activity_result(requestCode, resultCode, data)
Log.i("VOYEUR", "back from activity camera!")
end
@on_capture_click = proc do |view|
capture_intent = Intent.new(MediaStore::ACTION_IMAGE_CAPTURE)
capture_intent.putExtra(MediaStore::EXTRA_OUTPUT, Uri.fromFile(JFile.new("/sdcard/123.jpg")))
startActivityForResult(capture_intent, 1)
end
@on_edit_click = proc do |view|
RubotoActivity.edit(self)
end
end
end
end
RubotoActivity.launch $activity #, "$voyeur_activity"