Revision 41590feb
app/src/main/AndroidManifest.xml | ||
---|---|---|
15 | 15 |
|
16 | 16 |
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher_ssc" |
17 | 17 |
android:largeHeap="true" |
18 |
android:name=".App" |
|
18 |
android:name="org.witness.obscuracam.App"
|
|
19 | 19 |
android:theme="@style/AppTheme" |
20 | 20 |
> |
21 |
<activity android:label="@string/app_name_label" android:name=".MainActivity" |
|
21 |
<activity android:label="@string/app_name_label" android:name="org.witness.obscuracam.MainActivity"
|
|
22 | 22 |
android:description="@string/app_description" |
23 | 23 |
android:configChanges="orientation|keyboardHidden" |
24 | 24 |
android:theme="@style/AppTheme.NoActionBar" |
... | ... | |
28 | 28 |
<category android:name="android.intent.category.LAUNCHER" /> |
29 | 29 |
</intent-filter> |
30 | 30 |
</activity> |
31 |
<activity android:name="org.witness.securesmartcam.ImageEditor"
|
|
31 |
<activity android:name="org.witness.obscuracam.ui.ImageEditor"
|
|
32 | 32 |
android:configChanges="keyboardHidden|orientation|screenSize" |
33 | 33 |
android:theme="@style/AppTheme" |
34 | 34 |
> |
... | ... | |
46 | 46 |
</intent-filter> |
47 | 47 |
</activity> |
48 | 48 |
|
49 |
<activity android:name="org.witness.securesmartcam.ImagePreview" android:label="@string/image_preview" android:configChanges="orientation|keyboardHidden" />
|
|
49 |
<activity android:name="org.witness.obscuracam.ui.ImagePreview" android:label="@string/image_preview" android:configChanges="orientation|keyboardHidden" />
|
|
50 | 50 |
|
51 |
<activity android:name="org.witness.ssc.video.VideoEditor" android:configChanges="orientation|keyboardHidden|screenSize">
|
|
51 |
<activity android:name="org.witness.obscuracam.video.VideoEditor" android:configChanges="orientation|keyboardHidden|screenSize">
|
|
52 | 52 |
<intent-filter> |
53 | 53 |
|
54 | 54 |
<action android:name="android.intent.action.EDIT" /> |
... | ... | |
63 | 63 |
</intent-filter> |
64 | 64 |
|
65 | 65 |
</activity> |
66 |
<activity android:name="org.witness.ssc.video.VideoPreferences" />
|
|
66 |
<activity android:name="org.witness.obscuracam.video.VideoPreferences" />
|
|
67 | 67 |
<activity |
68 |
android:name="org.witness.securesmartcam.AlbumsActivity"
|
|
68 |
android:name="org.witness.obscuracam.ui.AlbumsActivity"
|
|
69 | 69 |
android:label="@string/title_albums" |
70 | 70 |
android:screenOrientation="portrait" |
71 | 71 |
android:theme="@style/AppTheme.NoActionBar" |
app/src/main/java/org/witness/obscuracam/App.java | ||
---|---|---|
1 |
package org.witness.obscuracam; |
|
2 |
|
|
3 |
import android.app.Application; |
|
4 |
import android.graphics.Bitmap; |
|
5 |
import android.media.ThumbnailUtils; |
|
6 |
import android.provider.MediaStore; |
|
7 |
|
|
8 |
import com.squareup.picasso.Picasso; |
|
9 |
import com.squareup.picasso.Request; |
|
10 |
import com.squareup.picasso.RequestHandler; |
|
11 |
|
|
12 |
import java.io.IOException; |
|
13 |
|
|
14 |
public class App extends Application { |
|
15 |
private static App gInstance; |
|
16 |
|
|
17 |
public static App getInstance() { |
|
18 |
return gInstance; |
|
19 |
} |
|
20 |
|
|
21 |
@Override |
|
22 |
public void onCreate() { |
|
23 |
gInstance = this; |
|
24 |
super.onCreate(); |
|
25 |
|
|
26 |
// Create thumbnails for video |
|
27 |
// |
|
28 |
Picasso.setSingletonInstance(new Picasso.Builder(this) |
|
29 |
.addRequestHandler(new RequestHandler() { |
|
30 |
@Override |
|
31 |
public boolean canHandleRequest(Request data) |
|
32 |
{ |
|
33 |
String scheme = data.uri.getScheme(); |
|
34 |
return ("video".equals(scheme)); |
|
35 |
} |
|
36 |
|
|
37 |
@Override |
|
38 |
public Result load(Request data, int arg1) throws IOException |
|
39 |
{ |
|
40 |
String path = data.uri.getPath(); |
|
41 |
Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(path, MediaStore.Video.Thumbnails.MICRO_KIND); |
|
42 |
return new Result(bitmap, Picasso.LoadedFrom.DISK); |
|
43 |
} |
|
44 |
}) |
|
45 |
//.indicatorsEnabled(true) |
|
46 |
.defaultBitmapConfig(Bitmap.Config.RGB_565) |
|
47 |
.build()); |
|
48 |
} |
|
49 |
} |
app/src/main/java/org/witness/obscuracam/MainActivity.java | ||
---|---|---|
1 |
package org.witness.obscuracam; |
|
2 |
|
|
3 |
|
|
4 |
import android.Manifest; |
|
5 |
import android.app.AlertDialog; |
|
6 |
import android.content.ClipData; |
|
7 |
import android.content.Intent; |
|
8 |
import android.content.pm.PackageManager; |
|
9 |
import android.content.pm.ResolveInfo; |
|
10 |
import android.content.res.Configuration; |
|
11 |
import android.net.Uri; |
|
12 |
import android.os.Build; |
|
13 |
import android.os.Bundle; |
|
14 |
import android.provider.MediaStore; |
|
15 |
import android.support.v4.app.ActivityCompat; |
|
16 |
import android.support.v4.content.ContextCompat; |
|
17 |
import android.support.v4.content.FileProvider; |
|
18 |
import android.support.v7.app.AppCompatActivity; |
|
19 |
import android.support.v7.widget.LinearLayoutManager; |
|
20 |
import android.support.v7.widget.RecyclerView; |
|
21 |
import android.support.v7.widget.Toolbar; |
|
22 |
import android.view.Menu; |
|
23 |
import android.view.MenuItem; |
|
24 |
import android.view.View; |
|
25 |
import android.widget.Button; |
|
26 |
|
|
27 |
import org.witness.obscuracam.ui.AlbumLayoutManager; |
|
28 |
import org.witness.obscuracam.ui.AlbumsActivity; |
|
29 |
import org.witness.obscuracam.ui.ImageEditor; |
|
30 |
import org.witness.obscuracam.ui.adapters.AskForPermissionAdapter; |
|
31 |
import org.witness.obscuracam.ui.adapters.GalleryCursorRecyclerViewAdapter; |
|
32 |
import org.witness.obscuracam.video.VideoEditor; |
|
33 |
import org.witness.sscphase1.R; |
|
34 |
|
|
35 |
import java.io.File; |
|
36 |
import java.io.IOException; |
|
37 |
import java.util.List; |
|
38 |
|
|
39 |
public class MainActivity extends AppCompatActivity implements GalleryCursorRecyclerViewAdapter.GalleryCursorRecyclerViewAdapterListener { |
|
40 |
|
|
41 |
public final static String TAG = "SSC"; |
|
42 |
|
|
43 |
private static final int READ_EXTERNAL_STORAGE_PERMISSION_REQUEST = 1; |
|
44 |
private static final int CAPTURE_IMAGE_REQUEST = 2; |
|
45 |
private static final int SELECT_FROM_ALBUMS_REQUEST = 3; |
|
46 |
|
|
47 |
private static final String CAMERA_CAPTURE_DIRNAME = "camera"; |
|
48 |
private static final String CAMERA_CAPTURE_FILENAME = "cameracapture"; |
|
49 |
|
|
50 |
final static int CAMERA_RESULT = 0; |
|
51 |
final static int GALLERY_RESULT = 1; |
|
52 |
final static int IMAGE_EDITOR = 2; |
|
53 |
final static int VIDEO_EDITOR = 3; |
|
54 |
final static int ABOUT = 0; |
|
55 |
|
|
56 |
private RecyclerView recyclerViewPhotos; |
|
57 |
private View layoutGalleryInfo; |
|
58 |
private AlbumLayoutManager layoutManagerPhotos; |
|
59 |
|
|
60 |
@Override |
|
61 |
protected void onDestroy() |
|
62 |
{ |
|
63 |
super.onDestroy(); |
|
64 |
deleteTmpFile(); |
|
65 |
|
|
66 |
} |
|
67 |
|
|
68 |
@Override |
|
69 |
public void onCreate(Bundle savedInstanceState) { |
|
70 |
super.onCreate(savedInstanceState); |
|
71 |
setContentView(R.layout.activity_main); |
|
72 |
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); |
|
73 |
setSupportActionBar(toolbar); |
|
74 |
deleteTmpFile(); |
|
75 |
|
|
76 |
layoutGalleryInfo = findViewById(R.id.gallery_info); |
|
77 |
Button btnOk = (Button) layoutGalleryInfo.findViewById(R.id.btnGalleryInfoOk); |
|
78 |
btnOk.setOnClickListener(new View.OnClickListener() { |
|
79 |
@Override |
|
80 |
public void onClick(View view) { |
|
81 |
//TODO App.getInstance().getSettings().setSkipGalleryInfo(true); |
|
82 |
layoutGalleryInfo.setVisibility(View.GONE); |
|
83 |
} |
|
84 |
}); |
|
85 |
layoutGalleryInfo.setVisibility(View.GONE); |
|
86 |
|
|
87 |
recyclerViewPhotos = (RecyclerView) findViewById(R.id.recycler_view_albums); |
|
88 |
int colWidth = getResources().getDimensionPixelSize(R.dimen.photo_column_size); |
|
89 |
layoutManagerPhotos = new AlbumLayoutManager(this, colWidth); |
|
90 |
recyclerViewPhotos.setLayoutManager(layoutManagerPhotos); |
|
91 |
|
|
92 |
setCurrentMode(); |
|
93 |
} |
|
94 |
|
|
95 |
@Override |
|
96 |
protected void onResume() { |
|
97 |
|
|
98 |
super.onResume(); |
|
99 |
|
|
100 |
} |
|
101 |
|
|
102 |
private void setLayout() { |
|
103 |
setContentView(R.layout.activity_main); |
|
104 |
recyclerViewPhotos = (RecyclerView) findViewById(R.id.recycler_view_albums); |
|
105 |
} |
|
106 |
|
|
107 |
/* protected void onActivityResult(int requestCode, int resultCode, Intent intent) { |
|
108 |
|
|
109 |
|
|
110 |
if (resultCode == RESULT_OK) |
|
111 |
{ |
|
112 |
setContentView(R.layout.mainloading); |
|
113 |
|
|
114 |
if (requestCode == GALLERY_RESULT) |
|
115 |
{ |
|
116 |
if (intent != null) |
|
117 |
{ |
|
118 |
Uri uriGalleryFile = intent.getData(); |
|
119 |
|
|
120 |
try |
|
121 |
{ |
|
122 |
if (uriGalleryFile != null) |
|
123 |
{ |
|
124 |
Cursor cursor = managedQuery(uriGalleryFile, null, |
|
125 |
null, null, null); |
|
126 |
cursor.moveToNext(); |
|
127 |
// Retrieve the path and the mime type |
|
128 |
String path = cursor.getString(cursor |
|
129 |
.getColumnIndex(MediaStore.MediaColumns.DATA)); |
|
130 |
String mimeType = cursor.getString(cursor |
|
131 |
.getColumnIndex(MediaStore.MediaColumns.MIME_TYPE)); |
|
132 |
|
|
133 |
if (mimeType == null || mimeType.startsWith("image")) |
|
134 |
{ |
|
135 |
Intent passingIntent = new Intent(this,ImageEditor.class); |
|
136 |
passingIntent.setData(uriGalleryFile); |
|
137 |
startActivityForResult(passingIntent,IMAGE_EDITOR); |
|
138 |
} |
|
139 |
else if (mimeType.startsWith("video")) |
|
140 |
{ |
|
141 |
|
|
142 |
Intent passingIntent = new Intent(this,VideoEditor.class); |
|
143 |
passingIntent.setData(uriGalleryFile); |
|
144 |
startActivityForResult(passingIntent,VIDEO_EDITOR); |
|
145 |
} |
|
146 |
} |
|
147 |
else |
|
148 |
{ |
|
149 |
Toast.makeText(this, "Unable to load media.", Toast.LENGTH_LONG).show(); |
|
150 |
|
|
151 |
} |
|
152 |
} |
|
153 |
catch (Exception e) |
|
154 |
{ |
|
155 |
Toast.makeText(this, "Unable to load media.", Toast.LENGTH_LONG).show(); |
|
156 |
Log.e(TAG, "error loading media: " + e.getMessage(), e); |
|
157 |
|
|
158 |
} |
|
159 |
} |
|
160 |
else |
|
161 |
{ |
|
162 |
Toast.makeText(this, "Unable to load photo.", Toast.LENGTH_LONG).show(); |
|
163 |
|
|
164 |
} |
|
165 |
|
|
166 |
} |
|
167 |
else if (requestCode == CAMERA_RESULT) |
|
168 |
{ |
|
169 |
//Uri uriCameraImage = intent.getData(); |
|
170 |
|
|
171 |
if (uriCameraImage != null) |
|
172 |
{ |
|
173 |
Intent passingIntent = new Intent(this,ImageEditor.class); |
|
174 |
passingIntent.setData(uriCameraImage); |
|
175 |
startActivityForResult(passingIntent,IMAGE_EDITOR); |
|
176 |
} |
|
177 |
else |
|
178 |
{ |
|
179 |
takePictureButton.setVisibility(View.VISIBLE); |
|
180 |
choosePictureButton.setVisibility(View.VISIBLE); |
|
181 |
} |
|
182 |
} |
|
183 |
} |
|
184 |
else |
|
185 |
setLayout(); |
|
186 |
|
|
187 |
|
|
188 |
|
|
189 |
} */ |
|
190 |
|
|
191 |
/* |
|
192 |
* Display the about screen |
|
193 |
*/ |
|
194 |
private void displayAbout() { |
|
195 |
|
|
196 |
StringBuffer msg = new StringBuffer(); |
|
197 |
|
|
198 |
msg.append(getString(R.string.app_name)); |
|
199 |
|
|
200 |
String versNum = ""; |
|
201 |
|
|
202 |
try { |
|
203 |
String pkg = getPackageName(); |
|
204 |
versNum = getPackageManager().getPackageInfo(pkg, 0).versionName; |
|
205 |
} catch (Exception e) { |
|
206 |
versNum = ""; |
|
207 |
} |
|
208 |
|
|
209 |
msg.append(" v" + versNum); |
|
210 |
msg.append('\n'); |
|
211 |
msg.append('\n'); |
|
212 |
|
|
213 |
msg.append(getString(R.string.about)); |
|
214 |
|
|
215 |
msg.append('\n'); |
|
216 |
msg.append('\n'); |
|
217 |
|
|
218 |
msg.append(getString(R.string.about2)); |
|
219 |
|
|
220 |
msg.append('\n'); |
|
221 |
msg.append('\n'); |
|
222 |
|
|
223 |
msg.append(getString(R.string.about3)); |
|
224 |
|
|
225 |
showDialog(msg.toString()); |
|
226 |
} |
|
227 |
|
|
228 |
private void showDialog (String msg) |
|
229 |
{ |
|
230 |
new AlertDialog.Builder(this) |
|
231 |
.setTitle(getString(R.string.app_name)) |
|
232 |
.setMessage(msg) |
|
233 |
.create().show(); |
|
234 |
} |
|
235 |
|
|
236 |
|
|
237 |
@Override |
|
238 |
public boolean onCreateOptionsMenu(Menu menu) { |
|
239 |
|
|
240 |
String aboutString = "About ObscuraCam"; |
|
241 |
|
|
242 |
MenuItem aboutMenuItem = menu.add(Menu.NONE, ABOUT, Menu.NONE, aboutString); |
|
243 |
aboutMenuItem.setIcon(R.drawable.ic_menu_about); |
|
244 |
|
|
245 |
|
|
246 |
return true; |
|
247 |
} |
|
248 |
|
|
249 |
public boolean onOptionsItemSelected(MenuItem item) { |
|
250 |
switch (item.getItemId()) { |
|
251 |
case ABOUT: |
|
252 |
displayAbout(); |
|
253 |
return true; |
|
254 |
|
|
255 |
default: |
|
256 |
|
|
257 |
return false; |
|
258 |
} |
|
259 |
} |
|
260 |
|
|
261 |
|
|
262 |
/* |
|
263 |
* Handling screen configuration changes ourselves, |
|
264 |
* we don't want the activity to restart on rotation |
|
265 |
*/ |
|
266 |
@Override |
|
267 |
public void onConfigurationChanged(Configuration conf) |
|
268 |
{ |
|
269 |
super.onConfigurationChanged(conf); |
|
270 |
// Reset the layout to use the landscape config |
|
271 |
setLayout(); |
|
272 |
} |
|
273 |
|
|
274 |
private void setCurrentMode() { |
|
275 |
int permissionCheck = ContextCompat.checkSelfPermission(this, |
|
276 |
Manifest.permission.READ_EXTERNAL_STORAGE); |
|
277 |
if (Build.VERSION.SDK_INT <= 18) |
|
278 |
permissionCheck = PackageManager.PERMISSION_GRANTED; // For old devices we ask in the manifest! |
|
279 |
if (permissionCheck != PackageManager.PERMISSION_GRANTED) { |
|
280 |
AskForPermissionAdapter adapter = new AskForPermissionAdapter(this); |
|
281 |
recyclerViewPhotos.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); |
|
282 |
recyclerViewPhotos.setAdapter(adapter); |
|
283 |
} else { |
|
284 |
applyCurrentMode(); |
|
285 |
} |
|
286 |
} |
|
287 |
|
|
288 |
public void askForReadExternalStoragePermission() { |
|
289 |
ActivityCompat.requestPermissions(this, new String[]{ |
|
290 |
Manifest.permission.READ_EXTERNAL_STORAGE, |
|
291 |
Manifest.permission.WRITE_EXTERNAL_STORAGE |
|
292 |
}, |
|
293 |
READ_EXTERNAL_STORAGE_PERMISSION_REQUEST); |
|
294 |
} |
|
295 |
|
|
296 |
@Override |
|
297 |
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { |
|
298 |
switch (requestCode) { |
|
299 |
case READ_EXTERNAL_STORAGE_PERMISSION_REQUEST: { |
|
300 |
// If request is cancelled, the result arrays are empty. |
|
301 |
if (grantResults.length > 1 |
|
302 |
&& grantResults[0] == PackageManager.PERMISSION_GRANTED |
|
303 |
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) { |
|
304 |
applyCurrentMode(); |
|
305 |
} |
|
306 |
} |
|
307 |
break; |
|
308 |
} |
|
309 |
} |
|
310 |
|
|
311 |
private void applyCurrentMode() { |
|
312 |
//TODO layoutGalleryInfo.setVisibility(App.getInstance().getSettings().skipGalleryInfo() ? View.GONE : View.VISIBLE); |
|
313 |
setPhotosAdapter(null, true, true); |
|
314 |
} |
|
315 |
|
|
316 |
private void setPhotosAdapter(String album, boolean showCamera, boolean showAlbums) { |
|
317 |
recyclerViewPhotos.setLayoutManager(layoutManagerPhotos); |
|
318 |
GalleryCursorRecyclerViewAdapter adapter = new GalleryCursorRecyclerViewAdapter(this, album, showCamera, showAlbums); |
|
319 |
adapter.setListener(this); |
|
320 |
int colWidth = getResources().getDimensionPixelSize(R.dimen.photo_column_size); |
|
321 |
layoutManagerPhotos.setColumnWidth(colWidth); |
|
322 |
recyclerViewPhotos.setAdapter(adapter); |
|
323 |
} |
|
324 |
|
|
325 |
@Override |
|
326 |
public void onPhotoSelected(String photo, View thumbView) { |
|
327 |
final Uri uri = Uri.parse(photo); |
|
328 |
if (uri != null) { |
|
329 |
try { |
|
330 |
Intent passingIntent = new Intent(this, ImageEditor.class); |
|
331 |
passingIntent.setData(uri); |
|
332 |
startActivityForResult(passingIntent, IMAGE_EDITOR); |
|
333 |
} catch (Exception e) { |
|
334 |
e.printStackTrace(); |
|
335 |
} |
|
336 |
} |
|
337 |
} |
|
338 |
|
|
339 |
@Override |
|
340 |
public void onVideoSelected(String photo, View thumbView) { |
|
341 |
final Uri uri = Uri.parse(photo); |
|
342 |
if (uri != null) { |
|
343 |
try { |
|
344 |
Intent passingIntent = new Intent(this, VideoEditor.class); |
|
345 |
passingIntent.setData(uri); |
|
346 |
startActivityForResult(passingIntent, VIDEO_EDITOR); |
|
347 |
} catch (Exception e) { |
|
348 |
e.printStackTrace(); |
|
349 |
} |
|
350 |
} |
|
351 |
} |
|
352 |
|
|
353 |
@Override |
|
354 |
public void onCameraSelected() { |
|
355 |
takePicture(); |
|
356 |
} |
|
357 |
|
|
358 |
@Override |
|
359 |
public void onAlbumsSelected() { |
|
360 |
Intent intentAlbums = new Intent(this, AlbumsActivity.class); |
|
361 |
startActivityForResult(intentAlbums, SELECT_FROM_ALBUMS_REQUEST); |
|
362 |
} |
|
363 |
|
|
364 |
private void takePicture() { |
|
365 |
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); |
|
366 |
if (takePictureIntent.resolveActivity(getPackageManager()) != null) { |
|
367 |
|
|
368 |
try { |
|
369 |
File storageDir = new File(getCacheDir(), CAMERA_CAPTURE_DIRNAME); |
|
370 |
if (!storageDir.exists()) { |
|
371 |
storageDir.mkdir(); |
|
372 |
} |
|
373 |
File image = new File(storageDir, CAMERA_CAPTURE_FILENAME); |
|
374 |
if (image.exists()) { |
|
375 |
image.delete(); |
|
376 |
} |
|
377 |
image.createNewFile(); |
|
378 |
|
|
379 |
Uri photoURI = FileProvider.getUriForFile(this, |
|
380 |
"org.witness.securesmartcam.camera_capture", |
|
381 |
image); |
|
382 |
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI); |
|
383 |
|
|
384 |
// Need to grant uri permissions, see here: |
|
385 |
// http://stackoverflow.com/questions/33650632/fileprovider-not-working-with-camera |
|
386 |
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) { |
|
387 |
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); |
|
388 |
} |
|
389 |
else if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.JELLY_BEAN) { |
|
390 |
ClipData clip= |
|
391 |
ClipData.newUri(getContentResolver(), "A photo", photoURI); |
|
392 |
|
|
393 |
takePictureIntent.setClipData(clip); |
|
394 |
takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); |
|
395 |
} |
|
396 |
else { |
|
397 |
List<ResolveInfo> resInfoList= |
|
398 |
getPackageManager() |
|
399 |
.queryIntentActivities(takePictureIntent, PackageManager.MATCH_DEFAULT_ONLY); |
|
400 |
|
|
401 |
for (ResolveInfo resolveInfo : resInfoList) { |
|
402 |
String packageName = resolveInfo.activityInfo.packageName; |
|
403 |
grantUriPermission(packageName, photoURI, |
|
404 |
Intent.FLAG_GRANT_WRITE_URI_PERMISSION); |
|
405 |
} |
|
406 |
} |
|
407 |
|
|
408 |
startActivityForResult(takePictureIntent, CAPTURE_IMAGE_REQUEST); |
|
409 |
} catch (IOException ignored) { |
|
410 |
} |
|
411 |
} |
|
412 |
} |
|
413 |
|
|
414 |
@Override |
|
415 |
protected void onActivityResult(int requestCode, int resultCode, Intent data) { |
|
416 |
if (requestCode == CAPTURE_IMAGE_REQUEST && resultCode == RESULT_OK) { |
|
417 |
try { |
|
418 |
File storageDir = new File(getCacheDir(), CAMERA_CAPTURE_DIRNAME); |
|
419 |
File image = new File(storageDir, CAMERA_CAPTURE_FILENAME); |
|
420 |
if (image.exists()) { |
|
421 |
onPhotoSelected(image.getAbsolutePath(), null); |
|
422 |
//TODO image.delete(); |
|
423 |
} |
|
424 |
} catch (Exception ignored) { |
|
425 |
} |
|
426 |
} else if (requestCode == SELECT_FROM_ALBUMS_REQUEST) { |
|
427 |
if (resultCode == RESULT_OK && data != null && data.hasExtra("uri")) { |
|
428 |
boolean isVideo = data.getBooleanExtra("video", false); |
|
429 |
if (isVideo) { |
|
430 |
onVideoSelected(data.getStringExtra("uri"), null); |
|
431 |
} else { |
|
432 |
onPhotoSelected(data.getStringExtra("uri"), null); |
|
433 |
} |
|
434 |
} |
|
435 |
} |
|
436 |
} |
|
437 |
|
|
438 |
private void deleteTmpFile () |
|
439 |
{ |
|
440 |
try { |
|
441 |
File storageDir = new File(getCacheDir(), CAMERA_CAPTURE_DIRNAME); |
|
442 |
if (!storageDir.exists()) { |
|
443 |
storageDir.mkdir(); |
|
444 |
} |
|
445 |
File image = new File(storageDir, CAMERA_CAPTURE_FILENAME); |
|
446 |
if (image.exists()) { |
|
447 |
image.delete(); |
|
448 |
} |
|
449 |
} catch (Exception ignored) {} |
|
450 |
} |
|
451 |
} |
app/src/main/java/org/witness/obscuracam/ObscuraApp.java | ||
---|---|---|
1 |
package org.witness.obscuracam; |
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
import java.io.File; |
|
6 |
|
|
7 |
import org.witness.obscuracam.ui.AlbumsActivity; |
|
8 |
import org.witness.obscuracam.ui.ImageEditor; |
|
9 |
import org.witness.obscuracam.video.VideoEditor; |
|
10 |
import org.witness.sscphase1.R; |
|
11 |
|
|
12 |
import android.app.AlertDialog; |
|
13 |
import android.content.ContentValues; |
|
14 |
import android.content.Intent; |
|
15 |
import android.content.res.Configuration; |
|
16 |
import android.database.Cursor; |
|
17 |
import android.net.Uri; |
|
18 |
import android.os.Bundle; |
|
19 |
import android.os.Environment; |
|
20 |
import android.provider.MediaStore; |
|
21 |
import android.support.v7.app.AppCompatActivity; |
|
22 |
import android.util.Log; |
|
23 |
import android.view.Menu; |
|
24 |
import android.view.MenuItem; |
|
25 |
import android.view.View; |
|
26 |
import android.view.View.OnClickListener; |
|
27 |
import android.view.Window; |
|
28 |
import android.widget.Button; |
|
29 |
import android.widget.Toast; |
|
30 |
|
|
31 |
public class ObscuraApp extends AppCompatActivity implements OnClickListener { |
|
32 |
|
|
33 |
public final static String TAG = "SSC"; |
|
34 |
|
|
35 |
final static int CAMERA_RESULT = 0; |
|
36 |
final static int GALLERY_RESULT = 1; |
|
37 |
final static int IMAGE_EDITOR = 2; |
|
38 |
final static int VIDEO_EDITOR = 3; |
|
39 |
final static int ABOUT = 0; |
|
40 |
|
|
41 |
final static String CAMERA_TMP_FILE = "ssctmp.jpg"; |
|
42 |
|
|
43 |
private Button choosePictureButton, chooseVideoButton, takePictureButton; |
|
44 |
|
|
45 |
private Uri uriCameraImage = null; |
|
46 |
|
|
47 |
@Override |
|
48 |
protected void onDestroy() |
|
49 |
{ |
|
50 |
super.onDestroy(); |
|
51 |
deleteTmpFile(); |
|
52 |
|
|
53 |
} |
|
54 |
|
|
55 |
private void deleteTmpFile () |
|
56 |
{ |
|
57 |
File fileDir = getExternalFilesDir(null); |
|
58 |
|
|
59 |
if (fileDir == null || !fileDir.exists()) |
|
60 |
fileDir = getFilesDir(); |
|
61 |
|
|
62 |
File tmpFile = new File(fileDir,CAMERA_TMP_FILE); |
|
63 |
if (tmpFile.exists()) |
|
64 |
tmpFile.delete(); |
|
65 |
} |
|
66 |
|
|
67 |
|
|
68 |
|
|
69 |
@Override |
|
70 |
public void onCreate(Bundle savedInstanceState) { |
|
71 |
super.onCreate(savedInstanceState); |
|
72 |
|
|
73 |
requestWindowFeature(Window.FEATURE_NO_TITLE); |
|
74 |
|
|
75 |
setLayout(); |
|
76 |
deleteTmpFile(); |
|
77 |
|
|
78 |
} |
|
79 |
|
|
80 |
@Override |
|
81 |
protected void onResume() { |
|
82 |
|
|
83 |
super.onResume(); |
|
84 |
|
|
85 |
|
|
86 |
} |
|
87 |
|
|
88 |
private void setLayout() { |
|
89 |
|
|
90 |
setContentView(R.layout.mainmenu); |
|
91 |
|
|
92 |
choosePictureButton = (Button) this.findViewById(R.id.ChoosePictureButton); |
|
93 |
choosePictureButton.setOnClickListener(this); |
|
94 |
|
|
95 |
chooseVideoButton = (Button) this.findViewById(R.id.ChooseVideoButton); |
|
96 |
chooseVideoButton.setOnClickListener(this); |
|
97 |
|
|
98 |
takePictureButton = (Button) this.findViewById(R.id.TakePictureButton); |
|
99 |
takePictureButton.setOnClickListener(this); |
|
100 |
|
|
101 |
} |
|
102 |
|
|
103 |
public void onClick(View v) { |
|
104 |
if (v == choosePictureButton) |
|
105 |
{ |
|
106 |
Intent intentAlbums = new Intent(this, AlbumsActivity.class); |
|
107 |
startActivityForResult(intentAlbums, 4711); //SELECT_FROM_ALBUMS_REQUEST); |
|
108 |
// try |
|
109 |
// { |
|
110 |
// setContentView(R.layout.mainloading); |
|
111 |
// Intent intent = new Intent(Intent.ACTION_PICK); |
|
112 |
// intent.setType("image/*"); //limit to image types for now |
|
113 |
// startActivityForResult(intent, GALLERY_RESULT); |
|
114 |
// |
|
115 |
// } |
|
116 |
// catch (Exception e) |
|
117 |
// { |
|
118 |
// Toast.makeText(this, "Unable to open Gallery app", Toast.LENGTH_LONG).show(); |
|
119 |
// Log.e(TAG, "error loading gallery app to choose photo: " + e.getMessage(), e); |
|
120 |
// } |
|
121 |
|
|
122 |
} |
|
123 |
else if (v == chooseVideoButton) |
|
124 |
{ |
|
125 |
|
|
126 |
try |
|
127 |
{ |
|
128 |
setContentView(R.layout.mainloading); |
|
129 |
Intent intent = new Intent(Intent.ACTION_PICK); |
|
130 |
intent.setType("video/*"); //limit to image types for now |
|
131 |
startActivityForResult(intent, GALLERY_RESULT); |
|
132 |
|
|
133 |
} |
|
134 |
catch (Exception e) |
|
135 |
{ |
|
136 |
Toast.makeText(this, "Unable to open Gallery app", Toast.LENGTH_LONG).show(); |
|
137 |
Log.e(TAG, "error loading gallery app to choose photo: " + e.getMessage(), e); |
|
138 |
} |
|
139 |
|
|
140 |
} |
|
141 |
else if (v == takePictureButton) { |
|
142 |
|
|
143 |
setContentView(R.layout.mainloading); |
|
144 |
|
|
145 |
String storageState = Environment.getExternalStorageState(); |
|
146 |
if(storageState.equals(Environment.MEDIA_MOUNTED)) { |
|
147 |
|
|
148 |
|
|
149 |
ContentValues values = new ContentValues(); |
|
150 |
|
|
151 |
values.put(MediaStore.Images.Media.TITLE, CAMERA_TMP_FILE); |
|
152 |
|
|
153 |
values.put(MediaStore.Images.Media.DESCRIPTION,"ssctmp"); |
|
154 |
|
|
155 |
File tmpFileDirectory = new File(Environment.getExternalStorageDirectory().getPath() + ImageEditor.TMP_FILE_DIRECTORY); |
|
156 |
if (!tmpFileDirectory.exists()) |
|
157 |
tmpFileDirectory.mkdirs(); |
|
158 |
|
|
159 |
File tmpFile = new File(tmpFileDirectory,"cam" + ImageEditor.TMP_FILE_NAME); |
|
160 |
|
|
161 |
uriCameraImage = Uri.fromFile(tmpFile); |
|
162 |
//uriCameraImage = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); |
|
163 |
|
|
164 |
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE ); |
|
165 |
intent.putExtra( MediaStore.EXTRA_OUTPUT, uriCameraImage); |
|
166 |
|
|
167 |
startActivityForResult(intent, CAMERA_RESULT); |
|
168 |
} else { |
|
169 |
new AlertDialog.Builder(ObscuraApp.this) |
|
170 |
.setMessage("External Storeage (SD Card) is required.\n\nCurrent state: " + storageState) |
|
171 |
.setCancelable(true).create().show(); |
|
172 |
} |
|
173 |
|
|
174 |
takePictureButton.setVisibility(View.VISIBLE); |
|
175 |
choosePictureButton.setVisibility(View.VISIBLE); |
|
176 |
chooseVideoButton.setVisibility(View.VISIBLE); |
|
177 |
|
|
178 |
} |
|
179 |
} |
|
180 |
|
|
181 |
protected void onActivityResult(int requestCode, int resultCode, Intent intent) { |
|
182 |
|
|
183 |
|
|
184 |
if (resultCode == RESULT_OK) |
|
185 |
{ |
|
186 |
setContentView(R.layout.mainloading); |
|
187 |
|
|
188 |
if (requestCode == GALLERY_RESULT) |
|
189 |
{ |
|
190 |
if (intent != null) |
|
191 |
{ |
|
192 |
Uri uriGalleryFile = intent.getData(); |
|
193 |
|
|
194 |
try |
|
195 |
{ |
|
196 |
if (uriGalleryFile != null) |
|
197 |
{ |
|
198 |
Cursor cursor = managedQuery(uriGalleryFile, null, |
|
199 |
null, null, null); |
|
200 |
cursor.moveToNext(); |
|
201 |
// Retrieve the path and the mime type |
|
202 |
String path = cursor.getString(cursor |
|
203 |
.getColumnIndex(MediaStore.MediaColumns.DATA)); |
|
204 |
String mimeType = cursor.getString(cursor |
|
205 |
.getColumnIndex(MediaStore.MediaColumns.MIME_TYPE)); |
|
206 |
|
|
207 |
if (mimeType == null || mimeType.startsWith("image")) |
|
208 |
{ |
|
209 |
Intent passingIntent = new Intent(this,ImageEditor.class); |
|
210 |
passingIntent.setData(uriGalleryFile); |
|
211 |
startActivityForResult(passingIntent,IMAGE_EDITOR); |
|
212 |
} |
|
213 |
else if (mimeType.startsWith("video")) |
|
214 |
{ |
|
215 |
|
|
216 |
Intent passingIntent = new Intent(this,VideoEditor.class); |
|
217 |
passingIntent.setData(uriGalleryFile); |
|
218 |
startActivityForResult(passingIntent,VIDEO_EDITOR); |
|
219 |
} |
|
220 |
} |
|
221 |
else |
|
222 |
{ |
|
223 |
Toast.makeText(this, "Unable to load media.", Toast.LENGTH_LONG).show(); |
|
224 |
|
|
225 |
} |
|
226 |
} |
|
227 |
catch (Exception e) |
|
228 |
{ |
|
229 |
Toast.makeText(this, "Unable to load media.", Toast.LENGTH_LONG).show(); |
|
230 |
Log.e(TAG, "error loading media: " + e.getMessage(), e); |
|
231 |
|
|
232 |
} |
|
233 |
} |
|
234 |
else |
|
235 |
{ |
|
236 |
Toast.makeText(this, "Unable to load photo.", Toast.LENGTH_LONG).show(); |
|
237 |
|
|
238 |
} |
|
239 |
|
|
240 |
} |
|
241 |
else if (requestCode == CAMERA_RESULT) |
|
242 |
{ |
|
243 |
//Uri uriCameraImage = intent.getData(); |
|
244 |
|
|
245 |
if (uriCameraImage != null) |
|
246 |
{ |
|
247 |
Intent passingIntent = new Intent(this,ImageEditor.class); |
|
248 |
passingIntent.setData(uriCameraImage); |
|
249 |
startActivityForResult(passingIntent,IMAGE_EDITOR); |
|
250 |
} |
|
251 |
else |
|
252 |
{ |
|
253 |
takePictureButton.setVisibility(View.VISIBLE); |
|
254 |
choosePictureButton.setVisibility(View.VISIBLE); |
|
255 |
} |
|
256 |
} |
|
257 |
} |
|
258 |
else |
|
259 |
setLayout(); |
|
260 |
|
|
261 |
|
|
262 |
|
|
263 |
} |
|
264 |
|
|
265 |
/* |
|
266 |
* Display the about screen |
|
267 |
*/ |
|
268 |
private void displayAbout() { |
|
269 |
|
|
270 |
StringBuffer msg = new StringBuffer(); |
|
271 |
|
|
272 |
msg.append(getString(R.string.app_name)); |
|
273 |
|
|
274 |
String versNum = ""; |
|
275 |
|
|
276 |
try { |
|
277 |
String pkg = getPackageName(); |
|
278 |
versNum = getPackageManager().getPackageInfo(pkg, 0).versionName; |
|
279 |
} catch (Exception e) { |
|
280 |
versNum = ""; |
|
281 |
} |
|
282 |
|
|
283 |
msg.append(" v" + versNum); |
|
284 |
msg.append('\n'); |
|
285 |
msg.append('\n'); |
|
286 |
|
|
287 |
msg.append(getString(R.string.about)); |
|
288 |
|
|
289 |
msg.append('\n'); |
|
290 |
msg.append('\n'); |
|
291 |
|
|
292 |
msg.append(getString(R.string.about2)); |
|
293 |
|
|
294 |
msg.append('\n'); |
|
295 |
msg.append('\n'); |
|
296 |
|
|
297 |
msg.append(getString(R.string.about3)); |
|
298 |
|
|
299 |
showDialog(msg.toString()); |
|
300 |
} |
|
301 |
|
|
302 |
private void showDialog (String msg) |
|
303 |
{ |
|
304 |
new AlertDialog.Builder(this) |
|
305 |
.setTitle(getString(R.string.app_name)) |
|
306 |
.setMessage(msg) |
|
307 |
.create().show(); |
|
308 |
} |
|
309 |
|
|
310 |
|
|
311 |
@Override |
|
312 |
public boolean onCreateOptionsMenu(Menu menu) { |
|
313 |
|
|
314 |
String aboutString = "About ObscuraCam"; |
|
315 |
|
|
316 |
MenuItem aboutMenuItem = menu.add(Menu.NONE, ABOUT, Menu.NONE, aboutString); |
|
317 |
aboutMenuItem.setIcon(R.drawable.ic_menu_about); |
|
318 |
|
|
319 |
|
|
320 |
return true; |
|
321 |
} |
|
322 |
|
|
323 |
public boolean onOptionsItemSelected(MenuItem item) { |
|
324 |
switch (item.getItemId()) { |
|
325 |
case ABOUT: |
|
326 |
displayAbout(); |
|
327 |
return true; |
|
328 |
|
|
329 |
default: |
|
330 |
|
|
331 |
return false; |
|
332 |
} |
|
333 |
} |
|
334 |
|
|
335 |
|
|
336 |
/* |
|
337 |
* Handling screen configuration changes ourselves, |
|
338 |
* we don't want the activity to restart on rotation |
|
339 |
*/ |
|
340 |
@Override |
|
341 |
public void onConfigurationChanged(Configuration conf) |
|
342 |
{ |
|
343 |
super.onConfigurationChanged(conf); |
|
344 |
// Reset the layout to use the landscape config |
|
345 |
setLayout(); |
|
346 |
} |
|
347 |
|
|
348 |
|
|
349 |
} |
app/src/main/java/org/witness/obscuracam/photo/detect/AndroidFaceDetection.java | ||
---|---|---|
1 |
package org.witness.obscuracam.photo.detect; |
|
2 |
|
|
3 |
import java.util.ArrayList; |
|
4 |
|
|
5 |
import android.graphics.Bitmap; |
|
6 |
import android.graphics.PointF; |
|
7 |
import android.graphics.RectF; |
|
8 |
import android.media.FaceDetector; |
|
9 |
import android.media.FaceDetector.Face; |
|
10 |
|
|
11 |
public class AndroidFaceDetection implements FaceDetection { |
|
12 |
|
|
13 |
public static final String LOGTAG = "AndroidFaceDetection"; |
|
14 |
|
|
15 |
public static int MAX_FACES = 10; |
|
16 |
|
|
17 |
Face[] faces = new Face[MAX_FACES]; |
|
18 |
FaceDetector faceDetector; |
|
19 |
|
|
20 |
int numFaces = 0; |
|
21 |
|
|
22 |
public final static float CONFIDENCE_FILTER = .15f; |
|
23 |
|
|
24 |
public AndroidFaceDetection(int width, int height) { |
|
25 |
|
|
26 |
faceDetector = new FaceDetector(width, height, MAX_FACES); |
|
27 |
|
|
28 |
} |
|
29 |
|
|
30 |
public void release () |
|
31 |
{ |
|
32 |
faceDetector = null; |
|
33 |
} |
|
34 |
|
|
35 |
public int findFaces(Bitmap bmp) { |
|
36 |
|
|
37 |
numFaces = faceDetector.findFaces(bmp, faces); |
|
38 |
return numFaces; |
|
39 |
} |
|
40 |
|
|
41 |
public ArrayList<DetectedFace> getFaces(int foundFaces) { |
|
42 |
|
|
43 |
ArrayList<DetectedFace> dFaces = new ArrayList<DetectedFace>(); |
|
44 |
|
|
45 |
for (int i = 0; i < foundFaces; i++) { |
|
46 |
|
|
47 |
if (faces[i].confidence() > CONFIDENCE_FILTER) |
|
48 |
{ |
|
49 |
PointF midPoint = new PointF(); |
|
50 |
|
|
51 |
float eyeDistance = faces[i].eyesDistance(); |
|
52 |
faces[i].getMidPoint(midPoint); |
|
53 |
|
|
54 |
// Create Rectangle |
|
55 |
/* |
|
56 |
float poseX = faces[i].pose(Face.EULER_X); |
|
57 |
float poseY = faces[i].pose(Face.EULER_Y); |
|
58 |
float poseZ = faces[i].pose(Face.EULER_Z); |
|
59 |
|
|
60 |
Log.i(LOGTAG,"euclid: " + poseX + "," + poseY + "," + poseZ); |
|
61 |
*/ |
|
62 |
|
|
63 |
float widthBuffer = eyeDistance * 1.5f; |
|
64 |
float heightBuffer = eyeDistance * 2f; |
|
65 |
RectF faceRect = new RectF((midPoint.x-widthBuffer), |
|
66 |
(midPoint.y-heightBuffer), |
|
67 |
(midPoint.x+widthBuffer), |
|
68 |
(midPoint.y+heightBuffer)); |
|
69 |
|
|
70 |
DetectedFace dFace = new DetectedFace(); |
|
71 |
dFace.bounds = faceRect; |
|
72 |
dFace.midpoint = midPoint; |
|
73 |
dFace.eyeDistance = eyeDistance; |
|
74 |
|
|
75 |
dFaces.add(dFace); |
|
76 |
} |
|
77 |
} |
|
78 |
|
|
79 |
return dFaces; |
|
80 |
} |
|
81 |
|
|
82 |
} |
app/src/main/java/org/witness/obscuracam/photo/detect/DetectedFace.java | ||
---|---|---|
1 |
package org.witness.obscuracam.photo.detect; |
|
2 |
|
|
3 |
import android.graphics.PointF; |
|
4 |
import android.graphics.RectF; |
|
5 |
|
|
6 |
public class DetectedFace { |
|
7 |
|
|
8 |
public RectF bounds; |
|
9 |
public PointF midpoint; |
|
10 |
public float eyeDistance; |
|
11 |
} |
app/src/main/java/org/witness/obscuracam/photo/detect/FaceDetection.java | ||
---|---|---|
1 |
package org.witness.obscuracam.photo.detect; |
|
2 |
|
|
3 |
import java.util.ArrayList; |
|
4 |
|
|
5 |
import android.graphics.Bitmap; |
|
6 |
|
|
7 |
public interface FaceDetection { |
|
8 |
int findFaces(Bitmap bmp); // returns number of faces |
|
9 |
ArrayList<DetectedFace> getFaces(int numberFound); // returns array of rectangles of found faces |
|
10 |
void release (); |
|
11 |
} |
app/src/main/java/org/witness/obscuracam/photo/filters/BlurObscure.java | ||
---|---|---|
1 |
/* |
|
2 |
* This ObscureMethod blurs the contents of the region |
|
3 |
*/ |
|
4 |
|
|
5 |
package org.witness.obscuracam.photo.filters; |
|
6 |
|
|
7 |
|
|
8 |
import java.util.Properties; |
|
9 |
|
|
10 |
import android.graphics.Bitmap; |
|
11 |
import android.graphics.Canvas; |
|
12 |
import android.graphics.Paint; |
|
13 |
import android.graphics.RectF; |
|
14 |
|
|
15 |
public class BlurObscure implements RegionProcesser { |
|
16 |
|
|
17 |
Bitmap originalBmp; |
|
18 |
Properties mProps; |
|
19 |
Paint mPaint; |
|
20 |
|
|
21 |
private final static int BLUR_OFFSET = 10; |
|
22 |
|
|
23 |
public BlurObscure(Paint paint) { |
|
24 |
mProps = new Properties (); |
|
25 |
mProps.put("obfuscationType", this.getClass().getName()); |
|
26 |
mPaint = paint; |
|
27 |
} |
|
28 |
|
|
29 |
public void processRegion(RectF rect, Canvas canvas, Bitmap bitmap) { |
|
30 |
|
|
31 |
Bitmap bRect = applyGaussianBlur(bitmap, rect); |
|
32 |
|
|
33 |
canvas.drawBitmap(bRect, (int)rect.left, (int)rect.top, mPaint); |
|
34 |
|
|
35 |
// return properties and data as a map |
|
36 |
mProps.put("initialCoordinates", "[" + rect.top + "," + rect.left + "]"); |
|
37 |
mProps.put("regionWidth", Float.toString(Math.abs(rect.left - rect.right))); |
|
38 |
mProps.put("regionHeight", Float.toString(Math.abs(rect.top - rect.bottom))); |
|
39 |
|
|
40 |
} |
|
41 |
|
|
42 |
public static Bitmap applyGaussianBlur(Bitmap src, RectF rect) { |
|
43 |
double[][] GaussianBlurConfig = new double[][] { |
|
44 |
{ 1, 2, 1 }, |
|
45 |
{ 2, 4, 2 }, |
|
46 |
{ 1, 2, 1 } |
|
47 |
}; |
|
48 |
ConvolutionMatrix convMatrix = new ConvolutionMatrix(3); |
|
49 |
convMatrix.applyConfig(GaussianBlurConfig); |
|
50 |
convMatrix.Factor = 16; |
|
51 |
convMatrix.Offset = 0; |
|
52 |
return ConvolutionMatrix.computeConvolution3x3(src, convMatrix, (int)rect.left,(int)rect.right,(int)rect.top,(int)rect.bottom); |
|
53 |
} |
|
54 |
|
|
55 |
/* |
|
56 |
private void makeItBlur(Rect rect) |
|
57 |
{ |
|
58 |
|
|
59 |
if (rect.left <= (0 + BLUR_OFFSET*2)) { |
|
60 |
rect.left = (1 + BLUR_OFFSET*2); |
|
61 |
} else if (rect.right >= (originalBmp.getWidth()-1-BLUR_OFFSET*2)) { |
|
62 |
rect.right = (originalBmp.getWidth() - 2 - BLUR_OFFSET*2); |
|
63 |
} |
|
64 |
|
|
65 |
if (rect.top <= (0 + BLUR_OFFSET*2)) { |
|
66 |
rect.top = (1 + BLUR_OFFSET*2); |
|
67 |
} else if (rect.bottom >= (originalBmp.getHeight() - BLUR_OFFSET*2)) { |
|
68 |
rect.bottom = (originalBmp.getHeight() - 2 - BLUR_OFFSET*2); |
|
69 |
} |
|
70 |
|
|
71 |
for (int x = rect.left; x < rect.right - 1; x++) { |
|
72 |
for (int y = rect.top; y < rect.bottom - 1; y++) { |
|
73 |
|
|
74 |
int blurOffset = (int)((Math.random()*BLUR_OFFSET)+BLUR_OFFSET); |
|
75 |
int r = getRed(x,y, blurOffset); |
|
76 |
|
|
77 |
blurOffset = (int)((Math.random()*BLUR_OFFSET)+BLUR_OFFSET); |
|
78 |
int g = getGreen(x,y, blurOffset); |
|
79 |
|
|
80 |
blurOffset = (int)((Math.random()*BLUR_OFFSET)+BLUR_OFFSET); |
|
81 |
int b = getBlue(x,y, blurOffset); |
|
82 |
|
|
83 |
originalBmp.setPixel(x, y, Color.rgb(r,g,b)); |
|
84 |
} |
|
85 |
} |
|
86 |
} |
|
87 |
|
|
88 |
|
|
89 |
private int getRed(int x, int y, int blurOffset) { |
|
90 |
return |
|
91 |
(Color.red(originalBmp.getPixel(x-blurOffset, y-blurOffset)) + |
|
92 |
Color.red(originalBmp.getPixel(x, y-blurOffset)) + |
|
93 |
Color.red(originalBmp.getPixel(x+blurOffset, y-blurOffset)) + |
|
94 |
Color.red(originalBmp.getPixel(x-blurOffset, y)) + |
|
95 |
Color.red(originalBmp.getPixel(x, y)) + |
|
96 |
Color.red(originalBmp.getPixel(x+blurOffset, y)) + |
|
97 |
Color.red(originalBmp.getPixel(x-blurOffset, y+blurOffset)) + |
|
98 |
Color.red(originalBmp.getPixel(x, y+blurOffset)) + |
|
99 |
Color.red(originalBmp.getPixel(x+blurOffset, y+blurOffset)))/9; |
|
100 |
} |
|
101 |
|
|
102 |
private int getGreen(int x, int y, int blurOffset) { |
|
103 |
return |
|
104 |
(Color.green(originalBmp.getPixel(x-blurOffset, y-blurOffset)) + |
|
105 |
Color.green(originalBmp.getPixel(x, y-blurOffset)) + |
|
106 |
Color.green(originalBmp.getPixel(x+blurOffset, y-blurOffset)) + |
|
107 |
Color.green(originalBmp.getPixel(x-blurOffset, y)) + |
|
108 |
Color.green(originalBmp.getPixel(x, y)) + |
|
109 |
Color.green(originalBmp.getPixel(x+blurOffset, y)) + |
|
110 |
Color.green(originalBmp.getPixel(x-blurOffset, y+blurOffset)) + |
|
111 |
Color.green(originalBmp.getPixel(x, y+blurOffset)) + |
|
112 |
Color.green(originalBmp.getPixel(x+blurOffset, y+blurOffset)))/9; |
|
113 |
} |
|
114 |
|
|
115 |
private int getBlue(int x, int y, int blurOffset) { |
|
116 |
return |
|
117 |
(Color.blue(originalBmp.getPixel(x-blurOffset, y-blurOffset)) + |
|
118 |
Color.blue(originalBmp.getPixel(x, y-blurOffset)) + |
|
119 |
Color.blue(originalBmp.getPixel(x+blurOffset, y-blurOffset)) + |
|
120 |
Color.blue(originalBmp.getPixel(x-blurOffset, y)) + |
|
121 |
Color.blue(originalBmp.getPixel(x, y)) + |
|
122 |
Color.blue(originalBmp.getPixel(x+blurOffset, y)) + |
|
123 |
Color.blue(originalBmp.getPixel(x-blurOffset, y+blurOffset)) + |
|
124 |
Color.blue(originalBmp.getPixel(x, y+blurOffset)) + |
|
125 |
Color.blue(originalBmp.getPixel(x+blurOffset, y+blurOffset)))/9; |
|
126 |
}*/ |
|
127 |
|
|
128 |
public Properties getProperties() |
|
129 |
{ |
|
130 |
return mProps; |
|
131 |
} |
|
132 |
|
|
133 |
public void setProperties(Properties props) |
|
134 |
{ |
|
135 |
mProps = props; |
|
136 |
} |
|
137 |
|
|
138 |
@Override |
|
139 |
public Bitmap getBitmap() { |
|
140 |
// TODO Auto-generated method stub |
|
141 |
return null; |
|
142 |
} |
|
143 |
|
|
144 |
} |
|
145 |
|
|
146 |
|
|
147 |
|
app/src/main/java/org/witness/obscuracam/photo/filters/ConsentTagger.java | ||
---|---|---|
1 |
package org.witness.obscuracam.photo.filters; |
|
2 |
|
|
3 |
import java.util.Properties; |
|
4 |
|
|
5 |
import android.graphics.Bitmap; |
|
6 |
import android.graphics.Canvas; |
|
7 |
import android.graphics.RectF; |
|
8 |
|
|
9 |
public class ConsentTagger implements RegionProcesser |
|
10 |
{ |
|
11 |
Properties mProps; |
|
12 |
private Bitmap mPreview; |
|
13 |
|
|
14 |
public ConsentTagger () |
|
15 |
{ |
|
16 |
mProps = new Properties (); |
|
17 |
mProps.put("regionSubject", ""); |
|
18 |
mProps.put("informedConsent", "false"); |
|
19 |
mProps.put("persistObscureType", "false"); |
|
20 |
mProps.put("obfuscationType", this.getClass().getName()); |
|
21 |
} |
|
22 |
|
|
23 |
@Override |
|
24 |
public void processRegion (RectF rect, Canvas canvas, Bitmap bitmap) |
|
25 |
{ |
|
26 |
// return properties and data as a map |
|
27 |
mProps.put("initialCoordinates", "[" + rect.top + "," + rect.left + "]"); |
|
28 |
mProps.put("regionWidth", Float.toString(Math.abs(rect.left - rect.right))); |
|
29 |
mProps.put("regionHeight", Float.toString(Math.abs(rect.top - rect.bottom))); |
|
30 |
mPreview = Bitmap.createBitmap( |
|
31 |
bitmap, |
|
32 |
(int) rect.left, |
|
33 |
(int) rect.top, |
|
34 |
(int) Math.min(bitmap.getWidth(),(Math.abs(rect.left - rect.right))), |
|
35 |
(int) Math.min(bitmap.getHeight(), (Math.abs(rect.top - rect.bottom))) |
|
36 |
); |
|
37 |
} |
|
38 |
|
|
39 |
public Properties getProperties() |
|
40 |
{ |
|
41 |
return mProps; |
|
42 |
} |
|
43 |
|
|
44 |
public void setProperties(Properties props) |
|
45 |
{ |
|
46 |
mProps = props; |
|
47 |
} |
|
48 |
|
|
49 |
@Override |
|
50 |
public Bitmap getBitmap() { |
|
51 |
// TODO Auto-generated method stub |
|
52 |
return mPreview; |
|
53 |
} |
|
54 |
} |
app/src/main/java/org/witness/obscuracam/photo/filters/ConvolutionMatrix.java | ||
---|---|---|
1 |
|
|
2 |
/* |
|
3 |
* Many thanks to Pete Houston |
|
4 |
* http://xjaphx.wordpress.com/2011/06/22/image-processing-convolution-matrix/ |
|
5 |
*/ |
|
6 |
package org.witness.obscuracam.photo.filters; |
|
7 |
|
|
8 |
import android.graphics.Bitmap; |
|
9 |
import android.graphics.Color; |
|
10 |
|
|
11 |
|
|
12 |
public class ConvolutionMatrix |
|
13 |
{ |
|
14 |
public static final int SIZE = 3; |
|
15 |
|
|
16 |
public double[][] Matrix; |
|
17 |
public double Factor = 1; |
|
18 |
public double Offset = 1; |
|
19 |
|
|
20 |
public ConvolutionMatrix(int size) { |
|
21 |
Matrix = new double[size][size]; |
|
22 |
} |
|
23 |
|
|
24 |
public void setAll(double value) { |
|
25 |
for (int x = 0; x < SIZE; ++x) { |
|
26 |
for (int y = 0; y < SIZE; ++y) { |
|
27 |
Matrix[x][y] = value; |
|
28 |
} |
|
29 |
} |
|
30 |
} |
|
31 |
|
|
32 |
public void applyConfig(double[][] config) { |
|
33 |
for(int x = 0; x < SIZE; ++x) { |
|
34 |
for(int y = 0; y < SIZE; ++y) { |
|
35 |
Matrix[x][y] = config[x][y]; |
|
36 |
} |
|
37 |
} |
|
38 |
} |
|
39 |
|
|
40 |
public static Bitmap computeConvolution3x3(Bitmap src, ConvolutionMatrix matrix, int left, int right, int top, int bottom) { |
|
41 |
|
|
42 |
Bitmap result = Bitmap.createBitmap(right-left, bottom-top, src.getConfig()); |
|
43 |
|
|
44 |
int A, R, G, B; |
|
45 |
int sumR, sumG, sumB; |
|
46 |
int[][] pixels = new int[SIZE][SIZE]; |
|
47 |
|
|
48 |
for(int y = top; y < bottom - 2; ++y) { |
|
49 |
for(int x = left; x < right - 2; ++x) { |
|
50 |
|
|
51 |
// get pixel matrix |
|
52 |
for(int i = 0; i < SIZE; ++i) { |
|
53 |
for(int j = 0; j < SIZE; ++j) { |
|
54 |
pixels[i][j] = src.getPixel(x + i, y + j); |
|
55 |
} |
|
56 |
} |
|
57 |
|
|
58 |
// get alpha of center pixel |
|
59 |
A = Color.alpha(pixels[1][1]); |
|
60 |
|
|
61 |
// init color sum |
|
62 |
sumR = sumG = sumB = 0; |
|
63 |
|
|
64 |
// get sum of RGB on matrix |
|
65 |
for(int i = 0; i < SIZE; ++i) { |
|
66 |
for(int j = 0; j < SIZE; ++j) { |
|
67 |
sumR += (Color.red(pixels[i][j]) * matrix.Matrix[i][j]); |
|
68 |
sumG += (Color.green(pixels[i][j]) * matrix.Matrix[i][j]); |
|
69 |
sumB += (Color.blue(pixels[i][j]) * matrix.Matrix[i][j]); |
|
70 |
} |
|
71 |
} |
|
72 |
|
|
73 |
// get final Red |
|
74 |
R = (int)(sumR / matrix.Factor + matrix.Offset); |
|
75 |
if(R < 0) { R = 0; } |
|
76 |
else if(R > 255) { R = 255; } |
|
77 |
|
|
78 |
// get final Green |
|
79 |
G = (int)(sumG / matrix.Factor + matrix.Offset); |
|
80 |
if(G < 0) { G = 0; } |
|
81 |
else if(G > 255) { G = 255; } |
|
82 |
|
|
83 |
// get final Blue |
|
84 |
B = (int)(sumB / matrix.Factor + matrix.Offset); |
|
85 |
if(B < 0) { B = 0; } |
|
86 |
else if(B > 255) { B = 255; } |
|
87 |
|
|
88 |
// apply new pixel |
|
89 |
result.setPixel(x - left + 1, y - top + 1, Color.argb(A, R, G, B)); |
|
90 |
} |
|
91 |
} |
|
92 |
|
|
93 |
// final image |
|
94 |
return result; |
|
95 |
} |
|
96 |
} |
app/src/main/java/org/witness/obscuracam/photo/filters/CrowdBlurObscure.java | ||
---|---|---|
1 |
/* |
|
2 |
* This ObscureMethod pixelizes the region |
|
3 |
*/ |
|
4 |
|
|
5 |
package org.witness.obscuracam.photo.filters; |
|
6 |
|
|
7 |
|
|
8 |
import java.util.Properties; |
|
9 |
|
|
10 |
import android.graphics.Bitmap; |
|
11 |
import android.graphics.Canvas; |
|
12 |
import android.graphics.RectF; |
|
13 |
|
|
14 |
public class CrowdBlurObscure implements RegionProcesser { |
|
15 |
|
|
16 |
Bitmap originalBmp; |
|
17 |
Properties mProps; |
|
18 |
|
|
19 |
public static int PIXEL_BLOCK = 50; |
|
20 |
|
|
21 |
public CrowdBlurObscure() { |
|
22 |
mProps = new Properties(); |
|
23 |
mProps.put("obfuscationType", this.getClass().getName()); |
|
24 |
} |
|
25 |
|
|
26 |
public void processRegion(RectF rect, Canvas canvas, Bitmap bitmap) { |
|
27 |
|
|
28 |
originalBmp = bitmap; |
|
29 |
|
|
30 |
int pixelSize = originalBmp.getWidth()/PIXEL_BLOCK; |
|
31 |
|
|
32 |
if (pixelSize <= 0) //1 is the smallest it can be |
|
33 |
pixelSize = 1; |
|
34 |
|
|
35 |
pixelate(rect, pixelSize); |
|
36 |
|
|
37 |
// return properties and data as a map |
|
38 |
mProps.put("initialCoordinates", "[" + rect.top + "," + rect.left + "]"); |
|
39 |
mProps.put("regionWidth", Float.toString(Math.abs(rect.left - rect.right))); |
|
40 |
mProps.put("regionHeight", Float.toString(Math.abs(rect.top - rect.bottom))); |
|
41 |
|
|
42 |
} |
|
43 |
|
|
44 |
private void pixelate(RectF rect, int pixelSize) |
|
45 |
{ |
|
46 |
if (rect.left <= 0) { |
|
47 |
rect.left = 1; |
|
48 |
} else if (rect.right >= originalBmp.getWidth()-1) { |
|
49 |
rect.right = originalBmp.getWidth() - 1; |
|
50 |
} |
|
51 |
|
|
52 |
if (rect.top <= 0) { |
|
53 |
rect.top = 1; |
|
54 |
} else if (rect.bottom >= originalBmp.getHeight()) { |
|
55 |
rect.bottom = originalBmp.getHeight(); |
|
56 |
} |
|
57 |
|
|
58 |
int px, py; |
|
59 |
|
|
60 |
for (int x = 0; x < originalBmp.getWidth() - 1; x+=pixelSize) { |
|
61 |
for (int y = 0; y < originalBmp.getHeight() - 1; y+=pixelSize) { |
|
62 |
|
|
63 |
if (rect.contains(x, y)) |
|
64 |
continue; |
|
65 |
|
|
66 |
px = (x/pixelSize)*pixelSize; |
|
67 |
py = (y/pixelSize)*pixelSize; |
|
68 |
|
|
69 |
try |
|
70 |
{ |
|
71 |
//originalBmp.setPixel(x, y, originalBmp.getPixel(px,py)); |
|
72 |
|
|
73 |
int pixels[] = new int[pixelSize*pixelSize]; |
|
74 |
int newPixel = originalBmp.getPixel(px, py); |
|
75 |
for (int i = 0; i < pixels.length; i++) |
|
76 |
pixels[i] = newPixel; |
|
77 |
|
|
78 |
originalBmp.setPixels(pixels, 0, pixelSize, px, py, pixelSize, pixelSize); |
|
79 |
} |
|
80 |
catch (IllegalArgumentException iae) |
|
81 |
{ |
|
82 |
//something is wrong with our pixel math |
|
83 |
break; //stop the filter |
|
84 |
} |
|
85 |
} |
|
86 |
} |
|
87 |
} |
|
88 |
|
|
89 |
public Properties getProperties() |
|
90 |
{ |
|
91 |
return mProps; |
|
92 |
} |
|
93 |
|
|
94 |
public void setProperties(Properties props) |
|
95 |
{ |
|
96 |
mProps = props; |
|
97 |
} |
|
98 |
|
|
99 |
@Override |
|
100 |
public Bitmap getBitmap() { |
|
101 |
// TODO Auto-generated method stub |
|
102 |
return null; |
|
103 |
} |
|
104 |
} |
|
105 |
|
|
106 |
|
|
107 |
|
|
108 |
|
app/src/main/java/org/witness/obscuracam/photo/filters/CrowdPixelizeObscure.java | ||
---|---|---|
1 |
/* |
|
2 |
* This ObscureMethod pixelizes the region |
|
3 |
*/ |
|
4 |
|
|
5 |
package org.witness.obscuracam.photo.filters; |
|
6 |
|
|
7 |
|
|
8 |
import java.util.Properties; |
|
9 |
|
|
10 |
import android.graphics.Bitmap; |
|
11 |
import android.graphics.Canvas; |
|
12 |
import android.graphics.RectF; |
|
13 |
|
|
14 |
public class CrowdPixelizeObscure implements RegionProcesser { |
|
15 |
|
|
16 |
Bitmap originalBmp; |
|
17 |
Properties mProps; |
|
18 |
|
|
19 |
public static int PIXEL_BLOCK = 50; |
|
20 |
|
|
21 |
public CrowdPixelizeObscure() { |
Also available in: Unified diff