Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

* Add files for the app.

  • Loading branch information...
commit 44f8d48c8fef54bf23503afda0b40d4f9e5eb8a0 1 parent e3762d3
@adstro adstro authored
Showing with 25,843 additions and 4 deletions.
  1. +14 −0 .gitignore
  2. +18 −0 JJIL-Android/AndroidManifest.xml
  3. BIN  JJIL-Android/libs/jjil.jar
  4. +40 −0 JJIL-Android/proguard.cfg
  5. +12 −0 JJIL-Android/project.properties
  6. BIN  JJIL-Android/res/drawable-hdpi/icon.png
  7. BIN  JJIL-Android/res/drawable-ldpi/icon.png
  8. BIN  JJIL-Android/res/drawable-mdpi/icon.png
  9. +12 −0 JJIL-Android/res/layout/main.xml
  10. +5 −0 JJIL-Android/res/values/strings.xml
  11. +42 −0 JJIL-Android/src/jjil/android/AndroidColors.java
  12. +61 −0 JJIL-Android/src/jjil/android/CrosshairOverlay.java
  13. +181 −0 JJIL-Android/src/jjil/android/DebugImage.java
  14. +288 −0 JJIL-Android/src/jjil/android/Ean13Barcode1D.java
  15. +144 −0 JJIL-Android/src/jjil/android/Error.java
  16. +9 −0 JJIL-Android/src/jjil/android/Gray8ImageAndroid.java
  17. +22 −0 JJIL-Android/src/jjil/android/Messages.java
  18. +54 −0 JJIL-Android/src/jjil/android/Nv212RgbImage.java
  19. +208 −0 JJIL-Android/src/jjil/android/Preview.java
  20. +58 −0 JJIL-Android/src/jjil/android/PreviewCallback.java
  21. +191 −0 JJIL-Android/src/jjil/android/ReadBarcode.java
  22. +64 −0 JJIL-Android/src/jjil/android/RgbImageAndroid.java
  23. +202 −0 LICENSE.txt
  24. +25 −0 NOTICE.txt
  25. +0 −4 README.md
  26. +125 −0 README.txt
  27. +3 −0  app/.gitignore
  28. +216 −0 app/AndroidManifest.xml
  29. +22 −0 app/assets/tts/apache.txt
  30. +1 −0  app/assets/tts/whatisandroid.txt
  31. +85 −0 app/build.xml
  32. +3 −0  app/default.properties
  33. BIN  app/libs/Androidplot-core-0.5.0-release.jar
  34. BIN  app/libs/android-support-v4.jar
  35. +40 −0 app/proguard.cfg
  36. +14 −0 app/project.properties
  37. BIN  app/res/drawable-hdpi/icon.png
  38. BIN  app/res/drawable-ldpi/icon.png
  39. BIN  app/res/drawable-mdpi/icon.png
  40. BIN  app/res/drawable/arrow_down_float.png
  41. +11 −0 app/res/drawable/emptyone.xml
  42. BIN  app/res/drawable/say.png
  43. +41 −0 app/res/layout-land/image_detectlogo.xml
  44. +41 −0 app/res/layout-land/image_detectlogo_better.xml
  45. +41 −0 app/res/layout-land/image_detectlogo_faster.xml
  46. +27 −0 app/res/layout-land/image_livecaptureplus.xml
  47. +6 −0 app/res/layout/address.xml
  48. +9 −0 app/res/layout/aoa_base.xml
  49. +158 −0 app/res/layout/clapperplay.xml
  50. +108 −0 app/res/layout/current_location.xml
  51. +157 −0 app/res/layout/determine_altitude.xml
  52. +69 −0 app/res/layout/determine_movement.xml
  53. +118 −0 app/res/layout/determine_orientation.xml
  54. +15 −0 app/res/layout/enterworddialog.xml
  55. +10 −0 app/res/layout/foodbrowselist.xml
  56. +17 −0 app/res/layout/foodbrowselist_entry.xml
  57. +62 −0 app/res/layout/fooddialog.xml
  58. +54 −0 app/res/layout/fooddialogmulti.xml
  59. +41 −0 app/res/layout/geocode.xml
  60. +51 −0 app/res/layout/image_barcode.xml
  61. +27 −0 app/res/layout/image_detectfaces.xml
  62. +27 −0 app/res/layout/image_detectlogo.xml
  63. +35 −0 app/res/layout/image_detectlogo_better.xml
  64. +27 −0 app/res/layout/image_detectlogo_faster.xml
  65. +8 −0 app/res/layout/image_livecapture.xml
  66. +82 −0 app/res/layout/image_livecaptureplus.xml
  67. +11 −0 app/res/layout/image_simplecapture.xml
  68. +38 −0 app/res/layout/magicword.xml
  69. +17 −0 app/res/layout/magicworddemo.xml
  70. +240 −0 app/res/layout/main.xml
  71. +83 −0 app/res/layout/nfc.xml
  72. +83 −0 app/res/layout/nfc_beam.xml
  73. +83 −0 app/res/layout/nfc_peer.xml
  74. +10 −0 app/res/layout/no_device.xml
  75. +132 −0 app/res/layout/proximity_alert.xml
  76. +13 −0 app/res/layout/sensor_display_temp.xml
  77. +17 −0 app/res/layout/sensor_main.xml
  78. +318 −0 app/res/layout/sensor_view.xml
  79. +32 −0 app/res/layout/sensors_north_main.xml
  80. +16 −0 app/res/layout/speechactivation_tagwriter.xml
  81. +58 −0 app/res/layout/speechactivationservice.xml
  82. +26 −0 app/res/layout/speechactivationstart_stop.xml
  83. +126 −0 app/res/layout/speechrecognition.xml
  84. +22 −0 app/res/layout/speechrecognition_result.xml
  85. +37 −0 app/res/layout/speechresult_listitem.xml
  86. +13 −0 app/res/layout/speechresultactivity_listitem.xml
  87. +120 −0 app/res/layout/texttospeech.xml
  88. +47 −0 app/res/layout/track_location.xml
  89. +26 −0 app/res/layout/ttsdemo.xml
  90. +22 −0 app/res/layout/ttsinfo.xml
  91. +13 −0 app/res/layout/ttsresult_listitem.xml
  92. +7 −0 app/res/menu/clapper_menu.xml
  93. +18 −0 app/res/menu/food_dialog_menu.xml
  94. +13 −0 app/res/menu/food_multi_dialog_menu.xml
  95. +8 −0 app/res/menu/magic_word_menu.xml
  96. +8 −0 app/res/menu/preferences_menu.xml
  97. +33 −0 app/res/menu/speech_menu.xml
  98. +18 −0 app/res/menu/tts_menu.xml
  99. BIN  app/res/raw/androidcalm.wav
  100. BIN  app/res/raw/enjoytestapplication.wav
  101. +47 −0 app/res/raw/foods.txt
  102. BIN  app/res/raw/highhz.wav
  103. BIN  app/res/raw/lowhigh.wav
  104. BIN  app/res/raw/lowhz.wav
  105. BIN  app/res/raw/midhz.wav
  106. BIN  app/res/raw/tone.wav
  107. +5 −0 app/res/values-v11/styles.xml
  108. +5 −0 app/res/values/bool.xml
  109. +42 −0 app/res/values/colors.xml
  110. +30 −0 app/res/values/fooddialog.xml
  111. +8 −0 app/res/values/mapkey.xml
  112. +15 −0 app/res/values/nfc_peer_strings.xml
  113. +17 −0 app/res/values/nfc_strings.xml
  114. +152 −0 app/res/values/pref_strings.xml
  115. +6 −0 app/res/values/sensors_strings.xml
  116. +300 −0 app/res/values/strings.xml
  117. +54 −0 app/res/values/style.xml
  118. +4 −0 app/res/xml/accessory_filter.xml
  119. +14 −0 app/res/xml/audio_clapper_preferences.xml
  120. +44 −0 app/res/xml/food_preferences.xml
  121. +64 −0 app/res/xml/speech_preferences.xml
  122. +56 −0 app/res/xml/tts_preferences.xml
  123. +146 −0 app/src/jjil/app/barcodereader/BarcodeReaderActivity.java
  124. +243 −0 app/src/root/gast/playground/GastAppActivity.java
  125. +51 −0 app/src/root/gast/playground/audio/AmplitudeLogWrapper.java
  126. +78 −0 app/src/root/gast/playground/audio/AudioClipLogWrapper.java
  127. +47 −0 app/src/root/gast/playground/audio/AudioTaskUtil.java
  128. +250 −0 app/src/root/gast/playground/audio/ClapperPlay.java
  129. +168 −0 app/src/root/gast/playground/audio/RecordAmplitudeTask.java
  130. +137 −0 app/src/root/gast/playground/audio/RecordAudioTask.java
  131. +75 −0 app/src/root/gast/playground/image/detectfaces/DetectFaces.java
  132. +80 −0 app/src/root/gast/playground/image/detectfaces/DetectFacesActivity.java
  133. +142 −0 app/src/root/gast/playground/image/detectlogo/DetectLogo.java
  134. +84 −0 app/src/root/gast/playground/image/detectlogo/DetectLogoActivity.java
  135. +161 −0 app/src/root/gast/playground/image/detectlogobetter/DetectLogo.java
  136. +84 −0 app/src/root/gast/playground/image/detectlogobetter/DetectLogoActivity.java
  137. +55 −0 app/src/root/gast/playground/image/detectlogobetter/FindBrightestPoint.java
  138. +112 −0 app/src/root/gast/playground/image/detectlogobetter/RgbAbsDiffGrayWb.java
  139. +146 −0 app/src/root/gast/playground/image/detectlogofaster/DetectLogo.java
  140. +80 −0 app/src/root/gast/playground/image/detectlogofaster/DetectLogoActivity.java
  141. +102 −0 app/src/root/gast/playground/image/livecapture/LiveCaptureActivity.java
  142. +211 −0 app/src/root/gast/playground/image/livecaptureplus/LiveCapturePlusActivity.java
  143. +78 −0 app/src/root/gast/playground/image/simplecapture/SimpleCaptureActivity.java
  144. +177 −0 app/src/root/gast/playground/location/CurrentLocationActivity.java
  145. +95 −0 app/src/root/gast/playground/location/FilteringLocationBroadcastReceiver.java
  146. +142 −0 app/src/root/gast/playground/location/GeocodeActivity.java
  147. +58 −0 app/src/root/gast/playground/location/LocationBean.java
  148. +80 −0 app/src/root/gast/playground/location/Point.java
  149. +166 −0 app/src/root/gast/playground/location/PointDatabaseManager.java
  150. +50 −0 app/src/root/gast/playground/location/PointOverlayItem.java
  151. +160 −0 app/src/root/gast/playground/location/ProximityAlertActivity.java
  152. +58 −0 app/src/root/gast/playground/location/ProximityAlertBroadcastReceiver.java
  153. +194 −0 app/src/root/gast/playground/location/ProximityAlertService.java
  154. +40 −0 app/src/root/gast/playground/location/ProximityPendingIntentFactory.java
  155. +250 −0 app/src/root/gast/playground/location/TrackLocationActivity.java
  156. +44 −0 app/src/root/gast/playground/location/TrackLocationBroadcastReceiver.java
  157. +138 −0 app/src/root/gast/playground/location/TrackLocationOverlay.java
  158. +487 −0 app/src/root/gast/playground/nfc/BeamInventoryActivity.java
  159. +476 −0 app/src/root/gast/playground/nfc/NFCInventoryActivity.java
  160. +512 −0 app/src/root/gast/playground/nfc/Peer2PeerNFCInventoryActivity.java
  161. +175 −0 app/src/root/gast/playground/pref/PreferenceHelper.java
  162. +140 −0 app/src/root/gast/playground/pref/SummarizingEditPreferences.java
  163. +146 −0 app/src/root/gast/playground/sensor/NorthFinder.java
  164. +402 −0 app/src/root/gast/playground/sensor/SensorDisplayFragment.java
  165. +43 −0 app/src/root/gast/playground/sensor/SensorListActivity.java
  166. +122 −0 app/src/root/gast/playground/sensor/SensorSelectorFragment.java
  167. +402 −0 app/src/root/gast/playground/sensor/altitude/DetermineAltitudeActivity.java
  168. +95 −0 app/src/root/gast/playground/sensor/aoa/AccessoryController.java
  169. +420 −0 app/src/root/gast/playground/sensor/aoa/BaseActivity.java
  170. +56 −0 app/src/root/gast/playground/sensor/aoa/UsbAccessoryActivity.java
  171. +265 −0 app/src/root/gast/playground/sensor/movement/AccelerationEventListener.java
  172. +308 −0 app/src/root/gast/playground/sensor/movement/DetermineMovementActivity.java
  173. +422 −0 app/src/root/gast/playground/sensor/orientation/DetermineOrientationActivity.java
  174. +229 −0 app/src/root/gast/playground/speech/SayMagicWordActivity.java
  175. +335 −0 app/src/root/gast/playground/speech/SayMagicWordDemo.java
  176. +129 −0 app/src/root/gast/playground/speech/SayMagicWordExecutorDemo.java
  177. +99 −0 app/src/root/gast/playground/speech/SpeechActivationServicePlay.java
  178. +191 −0 app/src/root/gast/playground/speech/SpeechActivatorStartStop.java
  179. +111 −0 app/src/root/gast/playground/speech/SpeechRecognitionLauncher.java
  180. +697 −0 app/src/root/gast/playground/speech/SpeechRecognitionPlay.java
  181. +126 −0 app/src/root/gast/playground/speech/SpeechRecognitionResultsActivity.java
  182. +117 −0 app/src/root/gast/playground/speech/SpeechResultAdapter.java
  183. +51 −0 app/src/root/gast/playground/speech/activation/ShowResultsSpeechActivationBroadcastReceiver.java
  184. +50 −0 app/src/root/gast/playground/speech/activation/SpeechActivationNfcTagReceiver.java
  185. +346 −0 app/src/root/gast/playground/speech/activation/SpeechActivatorTagWriter.java
  186. +101 −0 app/src/root/gast/playground/speech/activation/util/TagWriterActivity.java
  187. +112 −0 app/src/root/gast/playground/speech/activation/util/TagWriterExecutionActivity.java
  188. +100 −0 app/src/root/gast/playground/speech/food/FoodBrowser.java
  189. +433 −0 app/src/root/gast/playground/speech/food/FoodDialogPlay.java
  190. +28 −0 app/src/root/gast/playground/speech/food/FoodSpeechResultUnderstander.java
  191. +266 −0 app/src/root/gast/playground/speech/food/MultiTurnFoodDialogActivity.java
  192. +116 −0 app/src/root/gast/playground/speech/food/command/AddFood.java
  193. +82 −0 app/src/root/gast/playground/speech/food/command/AskForCalories.java
  194. +53 −0 app/src/root/gast/playground/speech/food/command/CancelCommand.java
  195. +114 −0 app/src/root/gast/playground/speech/food/command/FoodLookup.java
  196. +150 −0 app/src/root/gast/playground/speech/food/command/RemoveFood.java
  197. +57 −0 app/src/root/gast/playground/speech/food/command/WhichFoodGuesser.java
  198. +79 −0 app/src/root/gast/playground/speech/food/db/Food.java
  199. +288 −0 app/src/root/gast/playground/speech/food/db/FtsIndexedFoodDatabase.java
  200. +47 −0 app/src/root/gast/playground/speech/food/db/MatchedFood.java
  201. +48 −0 app/src/root/gast/playground/speech/food/lucene/FoodDocumentTranslator.java
  202. +68 −0 app/src/root/gast/playground/speech/food/lucene/FoodIndexBuilder.java
  203. +87 −0 app/src/root/gast/playground/speech/food/lucene/FoodSearcher.java
  204. +47 −0 app/src/root/gast/playground/speech/food/multimatcher/MultiPartUnderstander.java
  205. +96 −0 app/src/root/gast/playground/speech/food/multimatcher/MultiPartUnderstanderNoOrder.java
  206. +113 −0 app/src/root/gast/playground/speech/food/multimatcher/MultiPartUnderstanderOrdered.java
  207. +301 −0 app/src/root/gast/playground/speech/tts/TextToSpeechDemo.java
  208. +124 −0 app/src/root/gast/playground/speech/tts/TextToSpeechInfoActivity.java
  209. +633 −0 app/src/root/gast/playground/speech/tts/TextToSpeechPlay.java
  210. +94 −0 app/src/root/gast/playground/speech/visitor/MatchesTargetVisitor.java
  211. +49 −0 app/src/root/gast/playground/speech/visitor/MatchesTargetVisitorSoundex.java
  212. +42 −0 app/src/root/gast/playground/speech/visitor/MatchesTargetVisitorStem.java
  213. +86 −0 app/src/root/gast/playground/speech/visitor/PartialMatchTargetVisitor.java
  214. +15 −0 app/src/root/gast/playground/speech/visitor/SpeechResultVisitor.java
  215. +149 −0 app/src/root/gast/playground/util/DialogGenerator.java
  216. +46 −0 app/src/root/gast/playground/util/FileUtil.java
  217. +19 −0 appTest/AndroidManifest.xml
  218. +40 −0 appTest/proguard.cfg
  219. +12 −0 appTest/project.properties
  220. BIN  appTest/res/drawable-hdpi/ic_launcher.png
  221. BIN  appTest/res/drawable-ldpi/ic_launcher.png
  222. BIN  appTest/res/drawable-mdpi/ic_launcher.png
  223. +12 −0 appTest/res/layout/main.xml
  224. +7 −0 appTest/res/values/strings.xml
  225. +177 −0 appTest/src/root/gast/playground/speech/food/TestAndroidFtsDb.java
  226. +52 −0 appTest/src/root/gast/playground/speech/food/TestLuceneFoodMatcher.java
  227. +63 −0 appTest/src/root/gast/playground/speech/food/TestLuceneFoodQuery.java
  228. +58 −0 appTest/src/root/gast/playground/speech/food/lucene/TestLuceneFoodQuery.java
  229. +30 −0 appTest/src/root/gast/speech/text/TestSoundsLikeWordMatcher.java
  230. +28 −0 appTest/src/root/gast/speech/text/TestStemmedWordMatcher.java
  231. +18 −0 appTest/src/root/gast/speech/text/TestWordMatcher.java
  232. +83 −0 jjil/build.xml
  233. +233 −0 jjil/doc/allclasses-frame.html
  234. +233 −0 jjil/doc/allclasses-noframe.html
  235. +496 −0 jjil/doc/constant-values.html
  236. +146 −0 jjil/doc/deprecated-list.html
  237. +223 −0 jjil/doc/help-doc.html
  238. +161 −0 jjil/doc/index-files/index-1.html
  239. +148 −0 jjil/doc/index-files/index-10.html
  240. +155 −0 jjil/doc/index-files/index-11.html
  241. +176 −0 jjil/doc/index-files/index-12.html
  242. +148 −0 jjil/doc/index-files/index-13.html
  243. +375 −0 jjil/doc/index-files/index-14.html
  244. +223 −0 jjil/doc/index-files/index-15.html
  245. +283 −0 jjil/doc/index-files/index-16.html
  246. +279 −0 jjil/doc/index-files/index-17.html
  247. +145 −0 jjil/doc/index-files/index-18.html
  248. +154 −0 jjil/doc/index-files/index-19.html
  249. +163 −0 jjil/doc/index-files/index-2.html
  250. +145 −0 jjil/doc/index-files/index-20.html
  251. +228 −0 jjil/doc/index-files/index-3.html
Sorry, we could not display the entire diff because too many files (716) changed.
View
14 .gitignore
@@ -14,3 +14,17 @@ gen/
# Local configuration file (sdk path, etc)
local.properties
+
+db/*.sqlite3
+log/*.log
+tmp/**/*
+.prefs
+target
+log
+.settings
+workspace
+*~
+.DS_Store
+.svn
+nbproject
+.metadata
View
18 JJIL-Android/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="jjil.android"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <uses-sdk android:minSdkVersion="9" />
+
+ <application android:icon="@drawable/icon" android:label="@string/app_name">
+ <activity android:name=".JJILAndroidActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ </application>
+</manifest>
View
BIN  JJIL-Android/libs/jjil.jar
Binary file not shown
View
40 JJIL-Android/proguard.cfg
@@ -0,0 +1,40 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+ native <methods>;
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+ public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.app.Activity {
+ public void *(android.view.View);
+}
+
+-keepclassmembers enum * {
+ public static **[] values();
+ public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+ public static final android.os.Parcelable$Creator *;
+}
View
12 JJIL-Android/project.properties
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+android.library=true
+# Project target.
+target=android-15
View
BIN  JJIL-Android/res/drawable-hdpi/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  JJIL-Android/res/drawable-ldpi/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  JJIL-Android/res/drawable-mdpi/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
12 JJIL-Android/res/layout/main.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+<TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/hello"
+ />
+</LinearLayout>
View
5 JJIL-Android/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hello">Hello World, JJILAndroidActivity!</string>
+ <string name="app_name">JJIL-Android</string>
+</resources>
View
42 JJIL-Android/src/jjil/android/AndroidColors.java
@@ -0,0 +1,42 @@
+package jjil.android;
+
+import android.graphics.Color;
+
+public class AndroidColors {
+ /**
+ * Converts the YUV used in the Android NV21 format into an
+ * RGB value using code from
+ * http://msdn.microsoft.com/en-us/library/ms893078
+ * @param nY - y value (from WxH byte array)
+ * @param nU - u value (second byte in WxH/2 byte array)
+ * @param nV - v value (first byte in WxH/2 byte array)
+ * @return Android Color for the converted color
+ */
+ public static int yuv2Color(int nY, int nU, int nV) {
+ int nC = nY - 16;
+ int nD = nU - 128;
+ int nE = nV - 128;
+
+ int nR = Math.max(0, Math.min(255, (( 298 * nC + 409 * nE + 128) >> 8)));
+ int nG = Math.max(0, Math.min(255, (( 298 * nC - 100 * nD - 208 * nE + 128) >> 8)));
+ int nB = Math.max(0, Math.min(255, (( 298 * nC + 516 * nD + 128) >> 8)));
+ return Color.argb(255, nR, nG, nB);
+ }
+
+ /**
+ * Converts from RGB to YUV using code from
+ * http://msdn.microsoft.com/en-us/library/ms893078.
+ * Returns the value as a Android Color value in with the red byte
+ * is the Y value, green the U value, and blue the V value.
+ * @param nR - red value (0-255)
+ * @param nG - green value (0-255)
+ * @param nB - blue value (0-255)
+ * @return
+ */
+ public static int rgb2yuv(int nR, int nG, int nB) {
+ int nY = ( ( 66 * nR + 129 * nG + 25 * nB + 128) >> 8) + 16;
+ int nU = ( ( -38 * nR - 74 * nG + 112 * nB + 128) >> 8) + 128;
+ int nV = ( ( 112 * nR - 94 * nG - 18 * nB + 128) >> 8) + 128;
+ return Color.argb(255, nY, nU, nV);
+ }
+}
View
61 JJIL-Android/src/jjil/android/CrosshairOverlay.java
@@ -0,0 +1,61 @@
+package jjil.android;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class CrosshairOverlay extends View {
+ private Integer mnHorizStart, mnHorizEnd;
+ private Integer mnVertStart, mnVertEnd;
+
+ public CrosshairOverlay(Context context) {
+ super(context);
+ }
+
+ public CrosshairOverlay(Context context, AttributeSet attrs)
+ {
+ super(context, attrs);
+ }
+
+ public CrosshairOverlay(Context context, AttributeSet attrs, int defStyle)
+ {
+ super(context, attrs, defStyle);
+ }
+
+ public void clearLimits() {
+ mnHorizStart = mnHorizEnd = mnVertStart = mnVertEnd = null;
+ }
+
+ @Override
+ public void onDraw(Canvas c) {
+ super.onDraw(c);
+
+ // draw a partially transparent crosshairs on the canvas
+ Paint p = new Paint();
+ p.setColor(Color.RED);
+ p.setAlpha(128);
+ c.drawLine(0.0f, getHeight()/2, getWidth(), getHeight()/2, p);
+ c.drawLine(getWidth()/2, 0.0f, getWidth()/2, getHeight(), p);
+ if (mnHorizStart != null) {
+ c.drawLine(mnHorizStart, getHeight()/2-5, mnHorizStart, getHeight()/2+5, p);
+ c.drawLine(mnHorizEnd, getHeight()/2-5, mnHorizEnd, getHeight()/2+5, p);
+ }
+ if (mnVertStart != null) {
+ c.drawLine(getWidth()/2-5, mnVertStart, getWidth()/2+5, mnVertStart, p);
+ c.drawLine(getWidth()/2-5, mnVertEnd, getWidth()/2+5, mnVertEnd, p);
+ }
+ }
+
+ public void setHorizLimits(int nStart, int nEnd) {
+ mnHorizStart = nStart;
+ mnHorizEnd = nEnd;
+ }
+
+ public void setVertLimits(int nStart, int nEnd) {
+ mnVertStart = nStart;
+ mnVertEnd = nEnd;
+ }
+}
View
181 JJIL-Android/src/jjil/android/DebugImage.java
@@ -0,0 +1,181 @@
+package jjil.android;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import jjil.core.RgbVal;
+
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.os.Environment;
+
+public class DebugImage {
+ public static class Nv21Image {
+ public Nv21Image(byte[] data, int width, int height) {
+ this.mData = data;
+ this.mWidth = width;
+ this.mHeight = height;
+ }
+
+ public byte[] getData() {
+ return mData;
+ }
+
+ public int getHeight() {
+ return mHeight;
+ }
+
+ public int getWidth() {
+ return mWidth;
+ }
+
+ private byte[] mData;
+ private int mHeight, mWidth;
+ }
+ public static Nv21Image readGrayImage(String szFilename) {
+ Bitmap bmp = readBitmap(szFilename);
+ int width = bmp.getWidth();
+ int height = bmp.getHeight();
+ byte[] bResult = new byte[width * height];
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < width; j++) {
+ // turn the color image to gray
+ int pix = bmp.getPixel(j, i);
+ int r = (pix & 0x00ff0000) >> 16;
+ int g = (pix & 0x0000ff00) >> 8;
+ int b = (pix & 0x000000ff);
+ int gray = (r + g + b) / 3;
+ bResult[i * width + j] = RgbVal.unsignedIntToSignedByte[gray];
+ }
+ }
+ return new Nv21Image(bResult, width, height);
+ }
+
+ public static Nv21Image readImage2Nv21(String szFilename) {
+ Bitmap bmp = readBitmap(szFilename);
+ int width = bmp.getWidth();
+ int height = bmp.getHeight();
+ byte[] bResult = new byte[width * height + width * height / 2];
+ int nVuOffset = width * height;
+ // we compute the VU value on each 4 pixel block and the gray
+ // value on every pixel
+ for (int i = 0; i < height; i += 2) {
+ for (int j = 0; j < width; j += 2) {
+ int pix = bmp.getPixel(j, i);
+ int r = (pix & 0x00ff0000) >> 16;
+ int g = (pix & 0x0000ff00) >> 8;
+ int b = (pix & 0x000000ff);
+ int nSumR = r;
+ int nSumG = g;
+ int nSumB = b;
+ int nGray = (r + g + b) / 3;
+ bResult[i * width + j] = RgbVal.unsignedIntToSignedByte[nGray];
+ pix = bmp.getPixel(j + 1, i);
+ r = (pix & 0x00ff0000) >> 16;
+ g = (pix & 0x0000ff00) >> 8;
+ b = (pix & 0x000000ff);
+ nSumR += r;
+ nSumG += g;
+ nSumB += b;
+ nGray = (r + g + b) / 3;
+ bResult[i * width + j + 1] = RgbVal.unsignedIntToSignedByte[nGray];
+ pix = bmp.getPixel(j, i + 1);
+ r = (pix & 0x00ff0000) >> 16;
+ g = (pix & 0x0000ff00) >> 8;
+ b = (pix & 0x000000ff);
+ nSumR += r;
+ nSumG += g;
+ nSumB += b;
+ nGray = (r + g + b) / 3;
+ bResult[(i + 1) * width + j] = RgbVal.unsignedIntToSignedByte[nGray];
+ pix = bmp.getPixel(j + 1, i + 1);
+ r = (pix & 0x00ff0000) >> 16;
+ g = (pix & 0x0000ff00) >> 8;
+ b = (pix & 0x000000ff);
+ nSumR += r;
+ nSumG += g;
+ nSumB += b;
+ nGray = (r + g + b) / 3;
+ bResult[(i + 1) * width + j + 1] = RgbVal.unsignedIntToSignedByte[nGray];
+ // now compute the UV value for the 4-pixel block
+ int nYUV = AndroidColors.rgb2yuv(nSumR / 4, nSumG / 4,
+ nSumB / 4);
+ bResult[nVuOffset + i / 2 * width + j] = RgbVal.unsignedIntToSignedByte[nYUV & 0x000000ff];
+ bResult[nVuOffset + i / 2 * width + j + 1] = RgbVal.unsignedIntToSignedByte[(nYUV & 0x0000ff00) >> 8];
+ }
+ }
+ return new Nv21Image(bResult, width, height);
+ }
+
+ private static Bitmap readBitmap(String szFilename) {
+ File path = Environment
+ .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
+ File file = new File(path, szFilename);
+ return BitmapFactory.decodeFile(file.getAbsolutePath());
+ }
+
+ private static boolean writeBitmap(String szFilename, Bitmap bmp) {
+ try {
+ File path = Environment
+ .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
+ path.mkdirs();
+ File file = new File(path, szFilename);
+ OutputStream os = new FileOutputStream(file);
+ if (szFilename.toLowerCase().endsWith(".jpg")) {
+ bmp.compress(CompressFormat.JPEG, 100, os);
+ } else {
+ bmp.compress(CompressFormat.PNG, 100, os);
+ }
+ os.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return false;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean writeGrayImage(byte[] bImageData, int width,
+ int height, String szFilename) {
+ Bitmap bmp = Bitmap
+ .createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ int[] nImageData = new int[width * height];
+ for (int i = 0; i < width * height; i++) {
+ int nValue = 0xff & bImageData[i];
+ nImageData[i] = Color.argb(0xff, nValue, nValue, nValue);
+ }
+ bmp.setPixels(nImageData, 0, width, 0, 0, width, height);
+ return writeBitmap(szFilename, bmp);
+ }
+
+ public static boolean writeNv21Image(byte[] bImageData, int width,
+ int height, String szFilename) {
+ Bitmap bmp = Bitmap
+ .createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ int[] nImageData = new int[width * height];
+ int nVuOffset = width * height;
+ for (int i = 0; i < height; i++) {
+ // we produce two pixels for each VU pair in the color plane
+ for (int j = 0; j < width; j += 2) {
+ int nY = 0xff & bImageData[i * width + j];
+ int nV = 0xff & bImageData[nVuOffset + (i / 2) * width + j];
+ int nU = 0xff & bImageData[nVuOffset + (i / 2) * width + j + 1];
+ nImageData[i * width + j] = AndroidColors.yuv2Color(nY, nU, nV);
+ nY = 0xff & bImageData[i * width + j + 1];
+ nImageData[i * width + j + 1] = AndroidColors.yuv2Color(nY, nU,
+ nV);
+ }
+ }
+ bmp.setPixels(nImageData, 0, width, 0, 0, width, height);
+ return writeBitmap(szFilename, bmp);
+ }
+}
View
288 JJIL-Android/src/jjil/android/Ean13Barcode1D.java
@@ -0,0 +1,288 @@
+package jjil.android;
+
+import java.util.HashMap;
+
+public class Ean13Barcode1D {
+ /**
+ * Description of the barcode layout.
+ */
+ public static final int LEFT_DIGITS = 6; // number of digits in the left half of the barcode
+ public static final int RIGHT_DIGITS = 6; // number of digits in the right half of the barcode
+ public static final int LEFT_WIDTH = 3; // number of elementary bars in the left-side pattern
+ public static final int RIGHT_WIDTH = 3; // number of elementary bars in the right-side pattern
+ public static final int MID_WIDTH = 5; // number of elementary bars in the middle pattern
+ public static final int DIGIT_WIDTH = 7; // number of elementary bars in a digit
+ // the offset to the middle pattern, in elementary bars
+ public static final int MID_OFFSET = LEFT_WIDTH + LEFT_DIGITS*DIGIT_WIDTH;
+ // the offset to the right-side pattern, in elementary bars
+ public static final int RIGHT_OFFSET = LEFT_WIDTH +
+ (LEFT_DIGITS+RIGHT_DIGITS)*DIGIT_WIDTH + MID_WIDTH;
+ // the total number of elementary bars in a UPC barcode
+ public static final int TOTAL_WIDTH =
+ LEFT_WIDTH + DIGIT_WIDTH * LEFT_DIGITS + MID_WIDTH +
+ DIGIT_WIDTH * RIGHT_DIGITS + RIGHT_WIDTH;
+
+ public Ean13Barcode1D() {
+ initDigitCodes();
+ }
+
+ private void initDigitCodes()
+ {
+ /* The odd parity left (character set A) barcodes for the ten digits are:
+ 0 = 3-2-1-1 = 0001101 = 0x0d
+ 1 = 2-2-2-1 = 0011001 = 0x19
+ 2 = 2-1-2-2 = 0010011 = 0x13
+ 3 = 1-4-1-1 = 0111101 = 0x3d
+ 4 = 1-1-3-2 = 0100011 = 0x23
+ 5 = 1-2-3-1 = 0110001 = 0x31
+ 6 = 1-1-1-4 = 0101111 = 0x2f
+ 7 = 1-3-1-2 = 0111011 = 0x3b
+ 8 = 1-2-1-3 = 0110111 = 0x37
+ 9 = 3-1-1-2 = 0001011 = 0x0b
+ */
+ mhOddLeft = new HashMap<Integer, Character>();
+ mhOddLeft.put(0x0d, '0');
+ mhOddLeft.put(0x19, '1');
+ mhOddLeft.put(0x13, '2');
+ mhOddLeft.put(0x3d, '3');
+ mhOddLeft.put(0x23, '4');
+ mhOddLeft.put(0x31, '5');
+ mhOddLeft.put(0x2f, '6');
+ mhOddLeft.put(0x3b, '7');
+ mhOddLeft.put(0x37, '8');
+ mhOddLeft.put(0x0b, '9');
+ // The R barcodes for the digits are the 1-complements
+ // of the L odd barcodes. But we encode the R digits by
+ // encoding a white bar as 1 and a black bar as 0
+ // so we automatically get the 1-complement without
+ // while using the same table
+ /* The even parity left (character set B) barcodes for the ten digits are:
+ 0 = 1-1-2-3 = 0100111 = 0x27
+ 1 = 1-2-2-2 = 0110011 = 0x33
+ 2 = 2-2-1-2 = 0011011 = 0x1b
+ 3 = 1-1-4-1 = 0100001 = 0x21
+ 4 = 2-3-1-1 = 0011101 = 0x1d
+ 5 = 1-3-2-1 = 0111001 = 0x39
+ 6 = 4-1-1-1 = 0000101 = 0x05
+ 7 = 2-1-3-1 = 0010001 = 0x11
+ 8 = 3-1-2-1 = 0001001 = 0x09
+ 9 = 2-1-1-3 = 0010111 = 0x17
+ */
+ mhEvenLeft = new HashMap<Integer, Character>();
+ mhEvenLeft.put(0x27, '0');
+ mhEvenLeft.put(0x33, '1');
+ mhEvenLeft.put(0x1b, '2');
+ mhEvenLeft.put(0x21, '3');
+ mhEvenLeft.put(0x1d, '4');
+ mhEvenLeft.put(0x39, '5');
+ mhEvenLeft.put(0x05, '6');
+ mhEvenLeft.put(0x11, '7');
+ mhEvenLeft.put(0x09, '8');
+ mhEvenLeft.put(0x17, '9');
+ /**
+ * The first digit is implied based on
+ * the parity of the other digits in the
+ * left half. Below 1 = odd parity 0 = even
+ * 0 111111 = 0x3f
+ * 1 110100 = 0x34
+ * 2 110010 = 0x32
+ * 3 110001 = 0x31
+ * 4 101100 = 0x2c
+ * 5 100110 = 0x26
+ * 6 100011 = 0x23
+ * 7 101010 = 0x2a
+ * 8 101001 = 0x29
+ * 9 100101 = 0x25
+ */
+ mhFirstDigit = new HashMap<Integer, Character>();
+ mhFirstDigit.put(0x3f, '0');
+ mhFirstDigit.put(0x34, '1');
+ mhFirstDigit.put(0x32, '2');
+ mhFirstDigit.put(0x31, '3');
+ mhFirstDigit.put(0x2c, '4');
+ mhFirstDigit.put(0x26, '5');
+ mhFirstDigit.put(0x23, '6');
+ mhFirstDigit.put(0x2a, '7');
+ mhFirstDigit.put(0x29, '8');
+ mhFirstDigit.put(0x25, '9');
+ }
+
+ /**
+ * Decode an EAN-13 barcode from the image values in nValues, which should be
+ * thresholded at the value 'nMid', starting at position nStart and ending
+ * at position nEnd
+ * @param nValues -- the image values
+ * @param nStart -- column to start decoding the barcode
+ * @param nEnd -- column to end decoding the barcode
+ * @return the 13-digit decoded barcode if one was found, or null if not
+ */
+ public String decodeBarcode(byte[] bCompressed, int nStart) {
+ int nEnd = nStart + TOTAL_WIDTH;
+ // verify that the barcode starts and ends with the right patterns
+ if (bCompressed[nStart] != 1 || bCompressed[nStart+1] != 0 || bCompressed[nStart+2] != 1) {
+ return null;
+ }
+ if (bCompressed[nEnd-3] != 1 || bCompressed[nEnd-2] != 0 || bCompressed[nEnd-1] != 1) {
+ return null;
+ }
+ // skip past the marker on the left
+ int nCurr = LEFT_WIDTH + nStart;
+ StringBuilder sbBarcode = new StringBuilder();
+ int nLeftParity = 0;
+ // decode each digit, detecting the parity of each
+ for (int nDigit = 0; nDigit < LEFT_DIGITS; nDigit++) {
+ int nSum = 0;
+ // build an index into digitCodes for this pattern
+ for (int l = 0; l < DIGIT_WIDTH; l++) {
+ nSum = nSum * 2 + bCompressed[nCurr++];
+ }
+ if (nDigit == 0) {
+ // in EAN-13 the first digit always has odd parity
+ if (mhOddLeft.containsKey(nSum)) {
+ sbBarcode.append(mhOddLeft.get(nSum));
+ nLeftParity = 1;
+ } else {
+ // the first digit didn't match any of the codes
+ return null;
+ }
+ } else {
+ // determine the parity of the digit
+ if (mhOddLeft.containsKey(nSum)) {
+ sbBarcode.append(mhOddLeft.get(nSum));
+ nLeftParity = (nLeftParity * 2) + 1;
+ } else if (mhEvenLeft.containsKey(nSum)) {
+ sbBarcode.append(mhEvenLeft.get(nSum));
+ nLeftParity = nLeftParity * 2;
+ } else {
+ return sbBarcode.toString();
+ }
+ }
+ }
+ // check parity and add prefix character
+ if (mhFirstDigit.containsKey(nLeftParity)) {
+ sbBarcode.insert(0, mhFirstDigit.get(nLeftParity));
+ } else {
+ return sbBarcode.toString();
+ }
+ // now do the right side digits
+ nCurr += MID_WIDTH;
+ for (int nDigit = 0; nDigit < RIGHT_DIGITS; nDigit++) {
+ int nSum = 0;
+ // build an index into digitCodes for this pattern
+ for (int n = 0; n < DIGIT_WIDTH; n++) {
+ nSum = nSum * 2 + (1 - bCompressed[nCurr++]);
+ }
+ if (mhOddLeft.containsKey(nSum)) {
+ sbBarcode.append(mhOddLeft.get(nSum));
+ } else {
+ // the first digit didn't match any of the codes
+ return sbBarcode.toString();
+ }
+ }
+ return sbBarcode.toString();
+ }
+
+
+ public String searchForBarcode(int[] nValues, CrosshairOverlay co, boolean bHorizontal) {
+ // this is the number of pixels we look left and right to determine
+ // the local average.
+ final int LOCAL_THRESH = 32;
+
+ // compute the cumulative sum of nValues. We use this for local
+ // thresholding
+ int[] nCumulativeSum = new int[nValues.length];
+ nCumulativeSum[0] = nValues[0];
+ for (int i = 1; i < nValues.length; i++) {
+ nCumulativeSum[i] = nCumulativeSum[i - 1] + nValues[i];
+ }
+ for (int nPixelsPerBar = 1; nPixelsPerBar < nValues.length / TOTAL_WIDTH; nPixelsPerBar++) {
+
+ int nPixelSum = 0, nPixCount = 0, j = 0;
+ byte[] bCompressed = new byte[nValues.length];
+ for (int i = 0; i < nValues.length; i++) {
+ nPixelSum += nValues[i];
+ nPixCount++;
+ if (nPixCount == nPixelsPerBar) {
+ int nEnd = Math.min(nValues.length - 1, i + LOCAL_THRESH);
+ int nStart = Math.max(0, i - LOCAL_THRESH);
+ int nPixelValue = nPixelSum / nPixCount;
+ int nLocalAverage = (nCumulativeSum[nEnd] - nCumulativeSum[nStart])
+ / (nEnd - nStart);
+ if (nPixelValue > nLocalAverage) {
+ bCompressed[j++] = 0;
+ } else {
+ bCompressed[j++] = 1;
+ }
+ nPixelSum = 0;
+ nPixCount = 0;
+ }
+ }
+ // EAN-13 barcodes start and end with a black-white-black
+ // pattern preceded by white space. This is the bit pattern
+ // 00101 = 0x05, encoding white bars as 0 and dark bars as 1
+ int nStartCode = (bCompressed[0] << 3) + (bCompressed[1] << 2)
+ + (bCompressed[2] << 1) + (bCompressed[3]);
+ for (int i = 2; i < bCompressed.length - TOTAL_WIDTH - 2; i++) {
+ nStartCode = ((nStartCode & 0x0f) << 1) + bCompressed[i + 2];
+ if (nStartCode == 5) {
+ // found the left code, the right code will code as
+ // 10100 = 0x14 = 20
+ int nEndCode = (bCompressed[i + TOTAL_WIDTH - 3] << 4)
+ + (bCompressed[i + TOTAL_WIDTH - 2] << 3)
+ + (bCompressed[i + TOTAL_WIDTH - 1] << 2)
+ + (bCompressed[i + TOTAL_WIDTH] << 1)
+ + (bCompressed[i + TOTAL_WIDTH + 1]);
+ if (nEndCode == 20) {
+ if (co != null) {
+ if (bHorizontal) {
+ co.setHorizLimits(i*nPixelsPerBar, (i+TOTAL_WIDTH)*nPixelsPerBar);
+ } else {
+ co.setVertLimits(i*nPixelsPerBar, (i+TOTAL_WIDTH)*nPixelsPerBar);
+ }
+ }
+ String szBarcode = decodeBarcode(bCompressed, i);
+ if (szBarcode != null) {
+ return szBarcode;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Verifies the check digit in a decoded barcode string. Returns true
+ * if the check digit passes the verify test.
+ *
+ * @param digits the barcode to be verified.
+ * @return true iff the barcode passes the check digit test.
+ */
+ public static boolean verifyCheckDigit(String digits) {
+ if (digits == null || digits.length() != 13) {
+ return false;
+ }
+ // compute check digit
+ // add odd digits
+ int nOddSum = 0;
+ for (int i=1; i<digits.length()-1; i+=2) {
+ nOddSum += Character.digit(digits.charAt(i), 10);
+ }
+ // add even digits
+ int nEvenSum = 0;
+ for (int i=0;i<digits.length()-1; i+=2) {
+ nEvenSum += Character.digit(digits.charAt(i), 10);
+ }
+ // compute even digit sum * 3 + odd digit sum;
+ int nTotal = nOddSum*3 + nEvenSum;
+ // check digit is this sum subtracted from the next higher multiple of 10
+ int checkDigit = (nTotal/10 + 1) * 10 - nTotal;
+ return Character.digit(
+ digits.charAt(digits.length()-1), 10) == checkDigit;
+ }
+
+ /**
+ * Hashmaps for the various digit patterns
+ */
+ HashMap<Integer, Character> mhOddLeft, mhEvenLeft, mhFirstDigit;
+}
View
144 JJIL-Android/src/jjil/android/Error.java
@@ -0,0 +1,144 @@
+package jjil.android;
+
+/**
+ * This is the class used to create Strings from Error objects when running
+ * under Android. The point is that the Android localization support is used so
+ * the same approach won't work with J2ME, etc.<br>
+ * Usage:<br>
+ * jjil.android.Error eAndroid = new jjil.android.Error(e);<br>
+ * ... eAndroid.toString() ...
+ * @author webb
+ *
+ */
+public class Error extends jjil.core.Error {
+ private static final String szMessage[][] = new String[jjil.core.Error.PACKAGE.COUNT][];
+
+ {
+ Error.szMessage[jjil.core.Error.PACKAGE.CORE] = new String[jjil.core.ErrorCodes.COUNT];
+ Error.szMessage[jjil.core.Error.PACKAGE.CORE][jjil.core.ErrorCodes.BOUNDS_OUTSIDE_IMAGE] =
+ Messages.getString("BOUNDS_OUTSIDE_IMAGE");
+ Error.szMessage[jjil.core.Error.PACKAGE.CORE][jjil.core.ErrorCodes.ILLEGAL_PARAMETER_VALUE] =
+ Messages.getString("ILLEGAL_PARAMETER_VALUE");
+ Error.szMessage[jjil.core.Error.PACKAGE.CORE][jjil.core.ErrorCodes.IMAGE_MASK_SIZE_MISMATCH] =
+ Messages.getString("IMAGE_MASK_SIZE_MISMATCH");
+ Error.szMessage[jjil.core.Error.PACKAGE.CORE][jjil.core.ErrorCodes.MATH_DIVISION_ZERO] =
+ Messages.getString("MATH_DIVISION_ZERO");
+ Error.szMessage[jjil.core.Error.PACKAGE.CORE][jjil.core.ErrorCodes.MATH_NEGATIVE_SQRT] =
+ Messages.getString("MATH_NEGATIVE_SQRT");
+ Error.szMessage[jjil.core.Error.PACKAGE.CORE][jjil.core.ErrorCodes.MATH_PRODUCT_TOO_LARGE] =
+ Messages.getString("MATH_PRODUCT_TOO_LARGE");
+ Error.szMessage[jjil.core.Error.PACKAGE.CORE][jjil.core.ErrorCodes.MATH_SQUARE_TOO_LARGE] =
+ Messages.getString("MATH_SQUARE_TOO_LARGE");
+ Error.szMessage[jjil.core.Error.PACKAGE.CORE][jjil.core.ErrorCodes.NO_RESULT_AVAILABLE] =
+ Messages.getString("PIPELINE_NO_RESULT");
+ Error.szMessage[jjil.core.Error.PACKAGE.CORE][jjil.core.ErrorCodes.PIPELINE_EMPTY_PUSH] =
+ Messages.getString("PIPELINE_EMPTY_PUSH");
+
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM] = new String[jjil.algorithm.ErrorCodes.COUNT];
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.CONN_COMP_LABEL_COMPARETO_NULL] =
+ Messages.getString("CONN_COMP_LABEL_COMPARETO_NULL");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.CONN_COMP_LABEL_OUT_OF_BOUNDS] =
+ Messages.getString("CONN_COMP_LABEL_OUT_OF_BOUNDS");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.INPUT_TERMINATED_EARLY] =
+ Messages.getString("INPUT_TERMINATED_EARLY");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.FFT_SIZE_LARGER_THAN_MAX] =
+ Messages.getString("FFT_SIZE_LARGER_THAN_MAX");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.FFT_SIZE_NOT_POWER_OF_2] =
+ Messages.getString("FFT_SIZE_NOT_POWER_OF_2");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.HEAP_EMPTY] =
+ Messages.getString("HEAP_EMPTY");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.HISTOGRAM_LENGTH_NOT_256] =
+ Messages.getString("HISTOGRAM_LENGTH_NOT_256");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.ILLEGAL_COLOR_CHOICE] =
+ Messages.getString("ILLEGAL_COLOR_CHOICE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.IMAGE_NOT_COMPLEX32IMAGE] =
+ Messages.getString("IMAGE_NOT_COMPLEX32IMAGE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.IMAGE_NOT_GRAY16IMAGE] =
+ Messages.getString("IMAGE_NOT_GRAY16IMAGE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.IMAGE_NOT_GRAY32IMAGE] =
+ Messages.getString("IMAGE_NOT_GRAY32IMAGE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.IMAGE_NOT_GRAY8IMAGE] =
+ Messages.getString("IMAGE_NOT_GRAY8IMAGE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.IMAGE_NOT_RGBIMAGE] =
+ Messages.getString("IMAGE_NOT_RGBIMAGE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.IMAGE_NOT_SQUARE] =
+ Messages.getString("IMAGE_NOT_SQUARE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.IMAGE_SIZES_DIFFER] =
+ Messages.getString("IMAGE_SIZES_DIFFER");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.IMAGE_TOO_SMALL] =
+ Messages.getString("IMAGE_TOO_SMALL");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.INPUT_IMAGE_SIZE_NEGATIVE] =
+ Messages.getString("INPUT_IMAGE_SIZE_NEGATIVE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.INPUT_TERMINATED_EARLY] =
+ Messages.getString("INPUT_TERMINATED_EARLY");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.IO_EXCEPTION] =
+ Messages.getString("IO_EXCEPTION");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.LOOKUP_TABLE_LENGTH_NOT_256] =
+ Messages.getString("LOOKUP_TABLE_LENGTH_NOT_256");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.OBJECT_NOT_EXPECTED_TYPE] =
+ Messages.getString("OBJECT_NOT_EXPECTED_TYPE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.OUTPUT_IMAGE_SIZE_NEGATIVE] =
+ Messages.getString("OUTPUT_IMAGE_SIZE_NEGATIVE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.PARAMETER_OUT_OF_RANGE] =
+ Messages.getString("PARAMETER_OUT_OF_RANGE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.PARAMETER_RANGE_NULL_OR_NEGATIVE] =
+ Messages.getString("PARAMETER_RANGE_NULL_OR_NEGATIVE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.PARSE_ERROR] =
+ Messages.getString("PARSE_ERROR");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.REDUCE_INPUT_IMAGE_NOT_MULTIPLE_OF_OUTPUT_SIZE] =
+ Messages.getString("REDUCE_INPUT_IMAGE_NOT_MULTIPLE_OF_OUTPUT_SIZE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.SHRINK_OUTPUT_LARGER_THAN_INPUT] =
+ Messages.getString("SHRINK_OUTPUT_LARGER_THAN_INPUT");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.STATISTICS_VARIANCE_LESS_THAN_ZERO] =
+ Messages.getString("STATISTICS_VARIANCE_LESS_THAN_ZERO");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.STRETCH_OUTPUT_SMALLER_THAN_INPUT] =
+ Messages.getString("STRETCH_OUTPUT_SMALLER_THAN_INPUT");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.SUBIMAGE_NO_IMAGE_AVAILABLE] =
+ Messages.getString("SUBIMAGE_NO_IMAGE_AVAILABLE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.THRESHOLD_NEGATIVE] =
+ Messages.getString("THRESHOLD_NEGATIVE");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.WARP_END_LEFT_COL_GE_END_RIGHT_COL] =
+ Messages.getString("WARP_END_LEFT_COL_GE_END_RIGHT_COL");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.WARP_START_LEFT_COL_GE_START_RIGHT_COL] =
+ Messages.getString("WARP_START_LEFT_COL_GE_START_RIGHT_COL");
+ Error.szMessage[jjil.core.Error.PACKAGE.ALGORITHM][jjil.algorithm.ErrorCodes.WARP_START_ROW_GE_END_ROW] =
+ Messages.getString("WARP_START_ROW_GE_END_ROW");
+ }
+
+ public Error(jjil.core.Error e) {
+ super(e);
+ }
+
+ public String getLocalizedMessage() {
+ String szResult = null;
+ switch (this.getPackage()) {
+ case Error.PACKAGE.CORE:
+ if (this.getCode() < 0 || this.getCode() >= jjil.core.ErrorCodes.COUNT) {
+ szResult = Messages.getString("Illegal_error_code_core") +
+ new Integer(this.getCode()).toString();
+ } else {
+ szResult = szMessage[this.getPackage()][this.getCode()];
+ }
+ break;
+ case Error.PACKAGE.ALGORITHM:
+ if (this.getCode() < 0 || this.getCode() >= jjil.algorithm.ErrorCodes.COUNT) {
+ szResult = Messages.getString("Illegal_error_code_algorithm") +
+ new Integer(this.getCode()).toString();
+ } else {
+ szResult = szMessage[this.getPackage()][this.getCode()];
+ }
+ break;
+ case jjil.core.Error.PACKAGE.J2ME:
+ szResult = Messages.getString("Illegal_error_code_j2me") + " " +
+ new Integer(this.getCode()).toString();
+ break;
+ default:
+ szResult = Messages.getString("Illegal_error_code_package") + " " +
+ new Integer(this.getPackage()).toString() + " " +
+ new Integer(this.getCode()).toString();
+ break;
+ }
+ return szResult + ": " + parameters();
+ }
+
+}
View
9 JJIL-Android/src/jjil/android/Gray8ImageAndroid.java
@@ -0,0 +1,9 @@
+package jjil.android;
+
+import jjil.core.Gray8Image;
+
+public class Gray8ImageAndroid extends Gray8Image {
+ public Gray8ImageAndroid(int nWidth, int nHeight, byte[] rbYuvData) {
+ super(nWidth, nHeight, rbYuvData);
+ }
+}
View
22 JJIL-Android/src/jjil/android/Messages.java
@@ -0,0 +1,22 @@
+package jjil.android;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+ private static final String BUNDLE_NAME = "jjil.android.messages"; //$NON-NLS-1$
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+ .getBundle(BUNDLE_NAME);
+
+ private Messages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
View
54 JJIL-Android/src/jjil/android/Nv212RgbImage.java
@@ -0,0 +1,54 @@
+package jjil.android;
+
+import jjil.core.RgbImage;
+
+public class Nv212RgbImage {
+ public static RgbImage getRgbImage(byte[] data, int width, int height) {
+ RgbImage rgb = new RgbImage(width, height);
+ int nVuOffset = width * height;
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < width; j++) {
+ int nY = 0xff & data[i * width + j];
+ int nV = 0xff & data[nVuOffset + (i / 2) * width + (j / 2) * 2];
+ int nU = 0xff & data[nVuOffset + (i / 2) * width + (j / 2) * 2
+ + 1];
+ // AndroidColors.yuv2Color does exactly the right thing to
+ // convert
+ // into an RgbImage color
+ rgb.getData()[i * width + j] = AndroidColors.yuv2Color(nY, nU,
+ nV);
+ }
+ }
+ return rgb;
+ }
+
+ /**
+ * Returns a reduced size RGB image by averaging every 2x2 Y block and
+ * applying the corresponding VU pixels to get the color.
+ * @param data -- NV21 image
+ * @param width -- width of image
+ * @param height -- height of image
+ * @return a (width/2)x(height/2) RgbImage
+ */
+ public static RgbImage getRgbImageReduced(byte[] data, int width, int height) {
+ RgbImage rgb = new RgbImage(width / 2, height / 2);
+ int nVuOffset = width * height;
+ for (int i = 0; i < height; i += 2) {
+ for (int j = 0; j < width; j += 2) {
+ int nY = 0xff & data[i * width + j];
+ nY += 0xff & data[i * width + j + 1];
+ nY += 0xff & data[(i + 1) * width + j];
+ nY += 0xff & data[(i + 1) * width + j + 1];
+ nY /= 4;
+ int nV = 0xff & data[nVuOffset + (i / 2) * width + j];
+ int nU = 0xff & data[nVuOffset + (i / 2) * width + j + 1];
+ // AndroidColors.yuv2Color does exactly the right thing to
+ // convert
+ // into an RgbImage color
+ rgb.getData()[i / 2 * width / 2 + j / 2] = AndroidColors.yuv2Color(
+ nY, nU, nV);
+ }
+ }
+ return rgb;
+ }
+}
View
208 JJIL-Android/src/jjil/android/Preview.java
@@ -0,0 +1,208 @@
+package jjil.android;
+
+import java.io.IOException;
+import java.util.List;
+
+import android.content.Context;
+import android.hardware.Camera;
+import android.hardware.Camera.Size;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Display;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+/**
+ * A simple wrapper around a Camera and a SurfaceView that renders a centered preview of the Camera
+ * to the surface. We need to center the SurfaceView because not all devices have cameras that
+ * support preview sizes at the same aspect ratio as the device's display.
+ */
+public class Preview extends ViewGroup implements SurfaceHolder.Callback {
+ private final String TAG = "Preview";
+
+ public interface PreviewSizeChangedCallback {
+ void previewSizeChanged();
+ }
+
+ private Camera mCamera;
+ private SurfaceHolder mHolder;
+ private Size mPreviewSize;
+ private PreviewSizeChangedCallback mPreviewSizeChangedCallback = null;
+ private List<Size> mSupportedPreviewSizes;
+ private SurfaceView mSurfaceView;
+
+ public Preview(Context context, AttributeSet attributeSet) {
+ super(context, attributeSet);
+ mSurfaceView = new SurfaceView(context, attributeSet);
+ addView(mSurfaceView);
+ // Install a SurfaceHolder.Callback so we get notified when the
+ // underlying surface is created and destroyed.
+ mHolder = mSurfaceView.getHolder();
+ mHolder.addCallback(this);
+ mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+ }
+
+ public void setCamera(Camera camera) {
+ mCamera = camera;
+ if (mCamera != null) {
+ mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
+ requestLayout();
+ }
+ }
+
+ public void switchCamera(Camera camera) {
+ setCamera(camera);
+ try {
+ camera.setPreviewDisplay(mHolder);
+ } catch (IOException exception) {
+ Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
+ }
+ if (mSupportedPreviewSizes != null) {
+ mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes,
+ getMeasuredWidth(), getMeasuredHeight());
+ }
+ Camera.Parameters parameters = camera.getParameters();
+ parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
+ requestLayout();
+
+ try
+ {
+ camera.setParameters(parameters);
+ }
+ catch (RuntimeException e)
+ {
+ Log.e(TAG, "error setting parameters", e);
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // We purposely disregard child measurements because act as a
+ // wrapper to a SurfaceView that centers the camera preview instead
+ // of stretching it.
+ final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
+ final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
+ setMeasuredDimension(width, height);
+
+ if (mSupportedPreviewSizes != null) {
+ mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ if (changed && getChildCount() > 0) {
+ final View child = getChildAt(0);
+
+ final int width = r - l;
+ final int height = b - t;
+
+ int previewWidth = width;
+ int previewHeight = height;
+ if (mPreviewSize != null) {
+ previewWidth = mPreviewSize.width;
+ previewHeight = mPreviewSize.height;
+ }
+
+ // Center the child SurfaceView within the parent.
+ if (width * previewHeight > height * previewWidth) {
+ final int scaledChildWidth = previewWidth * height
+ / previewHeight;
+ child.layout((width - scaledChildWidth) / 2, 0,
+ (width + scaledChildWidth) / 2, height);
+ } else {
+ final int scaledChildHeight = previewHeight * width
+ / previewWidth;
+ child.layout(0, (height - scaledChildHeight) / 2, width,
+ (height + scaledChildHeight) / 2);
+ }
+ }
+ }
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ // The Surface has been created, acquire the camera and tell it where
+ // to draw.
+ try {
+ if (mCamera != null) {
+ mCamera.setPreviewDisplay(holder);
+ }
+ } catch (IOException exception) {
+ Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
+ }
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ // Surface will be destroyed when we return, so stop the preview.
+ if (mCamera != null) {
+ mCamera.stopPreview();
+ }
+ }
+
+
+ private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
+ final double ASPECT_TOLERANCE = 0.1;
+ double targetRatio = (double) w / h;
+ if (sizes == null) return null;
+
+ Size optimalSize = null;
+ double minDiff = Double.MAX_VALUE;
+
+ int targetHeight = h;
+
+ // Try to find an size match aspect ratio and size
+ for (Size size : sizes) {
+ double ratio = (double) size.width / size.height;
+ if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
+ if (Math.abs(size.height - targetHeight) < minDiff) {
+ optimalSize = size;
+ minDiff = Math.abs(size.height - targetHeight);
+ }
+ }
+
+ // Cannot find the one match the aspect ratio, ignore the requirement
+ if (optimalSize == null) {
+ minDiff = Double.MAX_VALUE;
+ for (Size size : sizes) {
+ if (Math.abs(size.height - targetHeight) < minDiff) {
+ optimalSize = size;
+ minDiff = Math.abs(size.height - targetHeight);
+ }
+ }
+ }
+ return optimalSize;
+ }
+
+ public void setPreviewSizeChangedCallback(PreviewSizeChangedCallback callback) {
+ mPreviewSizeChangedCallback = callback;
+ }
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ if (mCamera != null) {
+ // Now that the size is known, set up the camera parameters and
+ // begin
+ // the preview.
+ Camera.Parameters parameters = mCamera.getParameters();
+ parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
+ requestLayout();
+
+ try
+ {
+ mCamera.setParameters(parameters);
+ }
+ catch (RuntimeException e)
+ {
+ Log.e(TAG, "error setting parameters", e);
+ }
+
+ mCamera.startPreview();
+ if (mPreviewSizeChangedCallback != null) {
+ mPreviewSizeChangedCallback.previewSizeChanged();
+ }
+ }
+ }
+
+}
View
58 JJIL-Android/src/jjil/android/PreviewCallback.java
@@ -0,0 +1,58 @@
+package jjil.android;
+
+import android.graphics.ImageFormat;
+import android.hardware.Camera;
+import android.hardware.Camera.Size;
+
+public abstract class PreviewCallback implements android.hardware.Camera.PreviewCallback {
+
+ public abstract void ProcessFrame(int[][] frame);
+
+ @Override
+ public void onPreviewFrame(byte[] arg0, Camera arg1) {
+ int imageFormat = arg1.getParameters().getPreviewFormat();
+ Size size = arg1.getParameters().getPreviewSize();
+ for (int row = 0; row < size.height; row++) {
+ for (int col = 0; col < size.width; col++) {
+ switch(imageFormat) {
+ case ImageFormat.JPEG:
+ break;
+
+ case ImageFormat.NV16:
+ break;
+
+ case ImageFormat.NV21:
+ break;
+
+ case ImageFormat.RGB_565:
+ break;
+
+ case ImageFormat.UNKNOWN:
+ break;
+
+ case ImageFormat.YUY2: // aka YCbCr_422_I
+ /*
+ * The first question, however, is more difficult. The only specs I've
+ * been able to find on the 422 is that it's essentially 4 bytes of data
+ * with 2 pixels in it (equating to 6 rgb bytes. To "decompress" the
+ * data use the following algorithms.
+ * U = yuv[0]
+ * Y1 = yuv[1]
+ * V = yuv[2]
+ * Y2 = yuv[3]
+ * Then use equation to convert YUV to RGB is (remember to apply it to
+ * both Y1 and Y2):
+ * R = Y + 1.140V
+ * G = y - (0.395 * U) - (0.581 * V)
+ * B = Y + (2.032 * U)
+ */
+ break;
+
+ case ImageFormat.YV12:
+ break;
+ }
+ }
+ }
+ }
+
+}
View
191 JJIL-Android/src/jjil/android/ReadBarcode.java
@@ -0,0 +1,191 @@
+package jjil.android;
+
+import android.graphics.ImageFormat;
+import android.hardware.Camera;
+import android.hardware.Camera.Parameters;
+import android.hardware.Camera.Size;
+import android.os.Handler;
+import android.util.Log;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+public class ReadBarcode implements android.hardware.Camera.PreviewCallback,
+ android.hardware.Camera.AutoFocusCallback {
+
+ private static final String TAG = "ReadBarcode";
+
+ private Handler handler = new Handler();
+
+ public ReadBarcode(double dPerpPos, TextView tv, CheckBox ck, CrosshairOverlay co) {
+ me13b = new Ean13Barcode1D();
+ mdBarcodePerpPos = dPerpPos;
+ mTextViewResult = tv;
+ mCheckBoxResult = ck;
+ mCrosshairOverlay = co;
+ }
+
+ @Override
+ public void onAutoFocus(boolean success, Camera camera) {
+ Log.d(TAG, "on auto focus " + success);
+ if (!success) {
+ // try again
+
+ //code in the book was:
+// camera.autoFocus(this);
+ autoFocusLater(camera);
+ } else {
+ Log.d(TAG, "reset mnFocus");
+ mnFocused = 15;
+ }
+ }
+
+ @Override
+ public void onPreviewFrame(byte[] data, Camera camera) {
+ Parameters cameraParameters = camera.getParameters();
+ String focusMode = camera.getParameters().getFocusMode();
+ boolean bUseAutoFocus = focusMode.equals(Camera.Parameters.FOCUS_MODE_AUTO) ||
+ focusMode.equals(Camera.Parameters.FOCUS_MODE_MACRO);
+ if (bUseAutoFocus && (mnFocused == 0 || mbFoundBarcode)) {
+ Log.d(TAG, "exit, mnFocused is 0 or mbFoundBarcode is "
+ + mbFoundBarcode + " use auto " + bUseAutoFocus);
+ return;
+ }
+ try {
+ int imageFormat = cameraParameters.getPreviewFormat();
+ // we only know how to process NV21 format (the default format)
+ if (imageFormat == ImageFormat.NV21) {
+ /**
+ * NV21 consists of an 8-bit Y (intensity) plane followed by an
+ * interleaved subsampled U/V (hue) plane. We don't care about
+ * color in this app so we just read the intensity plane
+ */
+ Size size = camera.getParameters().getPreviewSize();
+ /**
+ * for debugging purposes, allow the current image to be saved
+ * and reused
+ */
+ boolean bWrite = false, bRead = false;
+ Integer width = size.width, height = size.height;
+ if (bWrite) {
+ DebugImage.writeGrayImage(data, width, height,
+ "barcode.png");
+ }
+ if (bRead) {
+ DebugImage.Nv21Image nv21Image = DebugImage.readGrayImage("barcode.png");
+ data = nv21Image.getData();
+ width = nv21Image.getWidth();
+ height = nv21Image.getHeight();
+ }
+ int[] nValues;
+ int nRow, nCol;
+ // First search for the barcode columnwise
+ nRow = (int) (mdBarcodePerpPos * height);
+ int nStartCol = 0;
+ int nEndCol = width;
+ nValues = new int[nEndCol - nStartCol];
+ int nRowOffset = width * nRow;
+ /**
+ * Byte values run from -128 (0x80) to + 127 (0x7f) but image
+ * values run from 0x00 to 0xff. It will be easier to do the
+ * math if we convert to integer. We also compute the max and
+ * min value to use in thresholding
+ */
+ int i = 0;
+ for (nCol = nStartCol; nCol < nEndCol; nCol++) {
+ int nValue = 0xff & (int) data[nRowOffset + nCol];
+ nValues[i++] = nValue;
+ }
+ String szBarcode = me13b.searchForBarcode(nValues, mCrosshairOverlay, true);
+ // show the barcode and exit
+ if (szBarcode != null && mTextViewResult != null) {
+ mTextViewResult.setText(szBarcode);
+ mbFoundBarcode = Ean13Barcode1D.verifyCheckDigit(szBarcode);
+ mCheckBoxResult.setChecked(mbFoundBarcode);
+ return;
+ }
+ // now search rowwsize
+ nCol = (int) (mdBarcodePerpPos * width);
+ int nStartRow = 0;
+ int nEndRow = height;
+ nValues = new int[nEndRow - nStartRow];
+ int nColOffset = nCol;
+ /**
+ * Byte values run from -128 (0x80) to + 127 (0x7f) but image
+ * values run from 0x00 to 0xff. It will be easier to do the
+ * math if we convert to integer. We also compute the max and
+ * min value to use in thresholding
+ */
+ i = 0;
+ for (nRow = nStartRow; nRow < nEndRow; nRow++) {
+ int nValue = 0xff & (int) data[nColOffset + nRow
+ * width];
+ nValues[i++] = nValue;
+ }
+ szBarcode = me13b.searchForBarcode(nValues, mCrosshairOverlay, false);
+ if (mTextViewResult != null && szBarcode != null) {
+ mTextViewResult.setText(szBarcode);
+ mbFoundBarcode = Ean13Barcode1D.verifyCheckDigit(szBarcode);
+ mCheckBoxResult.setChecked(mbFoundBarcode);
+ Log.d(TAG, "bar code");
+ return;
+ }
+ else
+ {
+ Log.d(TAG, "no bar code");
+ }
+ }
+ } finally {
+ if (bUseAutoFocus && (--mnFocused == 0 && !mbFoundBarcode)) {
+ Log.d(TAG, "refocusing");
+ //code in the book was:
+ //camera.autoFocus(this);
+ autoFocusLater(camera);
+ }
+ }
+ }
+
+ /**
+ * useful method for starting auto focus not too soon
+ */
+ public void autoFocusLater(final Camera camera)
+ {
+ final ReadBarcode finalContext = this;
+ handler.postDelayed(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ camera.autoFocus(finalContext);
+ }
+ catch (RuntimeException e)
+ {
+ Log.d(TAG, "error focusing, camera may be closing");
+ }
+ }
+ }, 100);
+ }
+
+ /**
+ * mbFocused is true when the camera has successfully autofocused
+ */
+ int mnFocused = 0;
+
+ /**
+ * 1D Barcode decoder
+ */
+ Ean13Barcode1D me13b;
+
+ /**
+ * The expected position of the barcode, measured perpendicular
+ * to the orientation of the barcode, from 0-1
+ */
+ double mdBarcodePerpPos;
+
+ private boolean mbFoundBarcode;
+ private TextView mTextViewResult;
+ private CheckBox mCheckBoxResult;
+ private CrosshairOverlay mCrosshairOverlay;
+
+}
View
64 JJIL-Android/src/jjil/android/RgbImageAndroid.java
@@ -0,0 +1,64 @@
+package jjil.android;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import jjil.core.RgbImage;
+import android.content.Context;
+import android.graphics.Bitmap;
+
+public class RgbImageAndroid {
+ /**
+ * The sole way to create an RgbImage from an image captured from the camera.
+ * The parameters are the pointer to the byte data passed to the JPEG picture
+ * callback and the width and height image you want. You must reduce the
+ * image size because otherwise you will run out of memory. Width and height
+ * reduction by a factor of 2 works on the GPhone.<p>
+ * Ex. usage<p>
+ * public void onPictureTaken(byte [] jpegData, android.hardware.Camera camera) {
+ * RgbImage rgb = RgbImageAndroid.toRgbImage(jpegData,
+ * camera.getParameters().getPictureSize().width/2,
+ * camera.getParameters().getPictureSize().height/2);
+ * }
+ * @param jpegData image data supplied to JpegPictureCallback
+ * @param nWidth target width image to return
+ * @param nHeight target height image to return
+ * @return RgbImage initialized with the image from the camera.
+ */
+ static public RgbImage toRgbImage(Bitmap bmp) {
+ int nWidth = bmp.getWidth();
+ int nHeight = bmp.getHeight();
+ RgbImage rgb = new RgbImage(nWidth, nHeight);
+ bmp.getPixels(rgb.getData(), 0, nWidth, 0, 0, nWidth, nHeight);
+ return rgb;
+ }
+
+ static public Bitmap toBitmap(RgbImage rgb)
+ {
+ return Bitmap.createBitmap(
+ rgb.getData(),
+ rgb.getWidth(),
+ rgb.getHeight(),
+ Bitmap.Config.ARGB_8888);
+ }
+
+ static public void toFile(Context context, RgbImage rgb, int nQuality, String szPath)
+ throws IOException
+ {
+ OutputStream os = new FileOutputStream(szPath);
+ try {
+ Bitmap bmp = toBitmap(rgb);
+ Bitmap.CompressFormat format = Bitmap.CompressFormat.JPEG;
+ szPath = szPath.toLowerCase();
+ if (szPath.endsWith("jpg") || szPath.endsWith("jpeg")) { //$NON-NLS-1$ //$NON-NLS-2$
+ format = Bitmap.CompressFormat.JPEG;
+ } else if (szPath.endsWith("png")) { //$NON-NLS-1$
+ format = Bitmap.CompressFormat.PNG;
+ }
+ bmp.compress(format, nQuality, os);
+ } finally {
+ os.close();
+ }
+ }
+}
View
202 LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
View
25 NOTICE.txt
@@ -0,0 +1,25 @@
+Great Android Sensing Toolkit (GAST)
+Copyright 2012 Greg Milette & Adam Stroud
+
+This product contains software developed by Google and shared in the Android
+developer site.
+ http://developer.android.com
+
+Portions of the image processing codebase where derived from John's Java Imaging
+Library (JJIL).
+ http://code.google.com/p/jjil
+
+Parts of the graphic codebase were derived from the Android API demos.
+ http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/index.html.
+
+The AOA example was derived from the example provided by Google as part of the
+Android developer reference.
+ http://developer.android.com/guide/topics/usb/adk.html
+
+The high-pass filter algorithm used in AccelerationEventListener was derived
+from the Android developer documentation.
+ http://developer.android.com/reference/android/hardware/SensorEvent.html
+
+Portions of the NFC examples were derived from the StickyNotes example from
+the android developer reference.
+ http://nfc.android.com/StickyNotes.zip
View
4 README.md
@@ -1,4 +0,0 @@
-gast-lib
-========
-
-The main gast-lib repository
View
125 README.txt
@@ -0,0 +1,125 @@
+
+================================================================================
+Professional Android Sensor Programming
+By Greg Milette and Adam Stroud
+Source Code
+================================================================================
+
+The files here contain the code from the book.
+All the code is licensed under the Apache 2.0 license. See LICENSE.txt for
+license details.
+
+================================================================================
+Great Android Sensing Toolkit (GAST)
+================================================================================
+
+The code in this book is also part of an open source project called Great
+Android Sensing Toolkit (GAST). See the Github site for the latest
+updates: https://github.com/gast-lib.
+
+The companion app to the book is also available on Google Play and can be
+downloaded from:
+https://play.google.com/store/apps/details?id=root.gast.playground.
+
+================================================================================
+ Software Requirements
+================================================================================
+
+The code was developed using the Eclipse IDE which is freely available from
+http://www.eclipse.org. In addition to eclipse, the Android SDK and Android
+developer's toolkit (ADT) will also need to be installed. See
+http://developer.android.com/sdk/index.html for instructions on installing the
+Android SDK and the ADT.
+
+================================================================================
+ Setup
+================================================================================
+
+Once the afore mentioned software packages have been installed, the source
+tree can be imported into Eclipse. The provided directories contain the
+necessary Eclipse project files. The projects associated with the code can
+be imported into Eclipse by selecting "Import..." from the Eclipse "File" menu.
+From the "Import" dialog, select "Existing Projects into Workspace" under the
+"General" folder and click "Next". From the next screen, click the "Browse"
+button and select the unzipped folder as the root directory. Once the unzipped
+folder has been selected, the "Projects" portion of the dialog should list the
+following projects that are available for import:
+
+* GastApp (/app)
+* GastAppTest (/appTest)
+* GastLibraryLuceneExt (/libraryLuceneExt)
+* GastLibrary (/library)
+* jjil (/jjil)
+* JJIL-Android (/JJIL-Android)
+* TemperatureSensor (/openaccessory)
+
+It is recommended to import all of the projects as this should create a
+workspace that has the ability to run the examples with very little
+"tweaking."
+
+Note: The directory names located on the filesystem DO NOT match the names of
+the projects. The filesystem directory names are located in the above list in
+parentheses where root ("/") is the directory that was created by expanding the
+.zip file.
+
+================================================================================
+ Projects
+================================================================================
+
+The following is a summary of the eclipse projects that can be imported from the
+previous section, as well as which chapters in the book reference the code:
+
+* GastApp - Contains the book's demonstration app called Android Sensing
+ Playground. It produces the APK that can be installed and run on an Android
+ device. It has code from all chapters.
+
+* GastAppTest - Contains unit tests for GastApp and GastLibrary.
+ It has code from chapter 17.
+
+* GastLibraryLuceneExt - Contains a Lucene related code for speech recognition.
+ It has code from chapter 17.
+
+* GastLibrary - Contains reusable code that supports the code from GastApp.
+ It has minimal dependencies so you can include only this project in your app.
+ It has code for various chapters in the book.
+
+* jjil - A clone of Jon's Java Imaging Library (http://code.google.com/p/jjil/)
+ with some updates for this book. It has code for chapters 12 and 13.
+
+* JJIL-Android - Another project from http://code.google.com/p/jjil/ with some
+ updates for this book. It has code for chapters 12 and 13.
+
+* openaccessory - Contains the code for Android Open Accessory (AOA).
+ It has code for chapter 10.
+
+================================================================================
+ Package Structure
+================================================================================
+
+The packages in GastApp are organized by sensor type and two categories:
+
+ * root.gast.playground.<sensor type> are from GastApp
+ * root.gast.<sensor type> are packages from other projects.
+
+When you are looking for code for a particular chapter or sensor look for the
+package with the appropriate sensor type.
+Part 1: root.gast.playground.location
+Part 2: root.gast.playground.sensor
+Chapter 10: com.example.temperaturesensor (in the openaccessory folder)
+Chapter 11: root.gast.playground.nfc
+Chapter 12,13: root.gast.playground.image
+Chapter 14: root.gast.playground.audio
+Part 4: root.gast.playground.speech
+
+================================================================================
+ Contact
+================================================================================
+
+We hope this code helps you understand how to use sensors and helps you get
+started using them.
+
+To contact the authors:
+Email: gastlib@gmail.com
+Github: https://github.com/gast-lib
+Wrox Programmer Forums: http://p2p.wrox.com/
+
View
3  app/.gitignore
@@ -0,0 +1,3 @@
+/gen
+/.settings
+/bin
View
216