├── .classpath
├── .gitignore
├── .project
├── AndroidManifest.xml
├── README.md
├── assets
└── tessdata
│ └── eng.traineddata
├── proguard.cfg
├── project.properties
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-ldpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── layout
│ └── main.xml
└── values
│ └── strings.xml
└── src
└── com
└── datumdroid
└── android
└── ocr
└── simple
└── SimpleAndroidOCRActivity.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled source #
2 | ###################
3 | *.com
4 | *.class
5 | *.dll
6 | *.exe
7 | *.o
8 | *.so
9 |
10 | # Packages #
11 | ############
12 | # it's better to unpack these files and commit the raw source
13 | # git has its own built in compression methods
14 | *.7z
15 | *.dmg
16 | *.gz
17 | *.iso
18 | *.jar
19 | *.rar
20 | *.tar
21 | *.zip
22 |
23 | # Logs and databases #
24 | ######################
25 | *.log
26 | *.sql
27 | *.sqlite
28 |
29 | # OS generated files #
30 | ######################
31 | .DS_Store*
32 | ehthumbs.db
33 | Icon?
34 | Thumbs.db
35 |
36 | # Custom #
37 | ##########
38 | bin/
39 | gen/
40 | .settings/
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | Simple-Android-OCR
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
15 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | For more information, check this tutorial: http://gaut.am/making-an-ocr-android-app-using-tesseract/
4 |
--------------------------------------------------------------------------------
/assets/tessdata/eng.traineddata:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GautamGupta/Simple-Android-OCR/53c77e74a0317a1b5246cc75b99271a52ad95e38/assets/tessdata/eng.traineddata
--------------------------------------------------------------------------------
/proguard.cfg:
--------------------------------------------------------------------------------
1 | -optimizationpasses 5
2 | -dontusemixedcaseclassnames
3 | -dontskipnonpubliclibraryclasses
4 | -dontpreverify
5 | -verbose
6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
7 |
8 | -keep public class * extends android.app.Activity
9 | -keep public class * extends android.app.Application
10 | -keep public class * extends android.app.Service
11 | -keep public class * extends android.content.BroadcastReceiver
12 | -keep public class * extends android.content.ContentProvider
13 | -keep public class * extends android.app.backup.BackupAgentHelper
14 | -keep public class * extends android.preference.Preference
15 | -keep public class com.android.vending.licensing.ILicensingService
16 |
17 | -keepclasseswithmembernames class * {
18 | native ;
19 | }
20 |
21 | -keepclasseswithmembers class * {
22 | public (android.content.Context, android.util.AttributeSet);
23 | }
24 |
25 | -keepclasseswithmembers class * {
26 | public (android.content.Context, android.util.AttributeSet, int);
27 | }
28 |
29 | -keepclassmembers class * extends android.app.Activity {
30 | public void *(android.view.View);
31 | }
32 |
33 | -keepclassmembers enum * {
34 | public static **[] values();
35 | public static ** valueOf(java.lang.String);
36 | }
37 |
38 | -keep class * implements android.os.Parcelable {
39 | public static final android.os.Parcelable$Creator *;
40 | }
41 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system use,
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 |
10 | # Project target.
11 | target=android-10
12 | android.library.reference.1=../tess-two
13 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GautamGupta/Simple-Android-OCR/53c77e74a0317a1b5246cc75b99271a52ad95e38/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GautamGupta/Simple-Android-OCR/53c77e74a0317a1b5246cc75b99271a52ad95e38/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/GautamGupta/Simple-Android-OCR/53c77e74a0317a1b5246cc75b99271a52ad95e38/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
18 |
19 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello World, DatumDroidOCRActivity!
5 | Simple Android OCR
6 | OCR!
7 | OCRed Text will appear here
8 |
9 |
--------------------------------------------------------------------------------
/src/com/datumdroid/android/ocr/simple/SimpleAndroidOCRActivity.java:
--------------------------------------------------------------------------------
1 | package com.datumdroid.android.ocr.simple;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileOutputStream;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.io.OutputStream;
9 | import java.util.zip.GZIPInputStream;
10 |
11 | import android.app.Activity;
12 | import android.content.Intent;
13 | import android.content.res.AssetManager;
14 | import android.graphics.Bitmap;
15 | import android.graphics.BitmapFactory;
16 | import android.graphics.Matrix;
17 | import android.media.ExifInterface;
18 | import android.net.Uri;
19 | import android.os.Bundle;
20 | import android.os.Environment;
21 | import android.provider.MediaStore;
22 | import android.util.Log;
23 | import android.view.View;
24 | import android.widget.Button;
25 | import android.widget.EditText;
26 |
27 | import com.googlecode.tesseract.android.TessBaseAPI;
28 |
29 | public class SimpleAndroidOCRActivity extends Activity {
30 | public static final String PACKAGE_NAME = "com.datumdroid.android.ocr.simple";
31 | public static final String DATA_PATH = Environment
32 | .getExternalStorageDirectory().toString() + "/SimpleAndroidOCR/";
33 |
34 | // You should have the trained data file in assets folder
35 | // You can get them at:
36 | // https://github.com/tesseract-ocr/tessdata
37 | public static final String lang = "eng";
38 |
39 | private static final String TAG = "SimpleAndroidOCR.java";
40 |
41 | protected Button _button;
42 | // protected ImageView _image;
43 | protected EditText _field;
44 | protected String _path;
45 | protected boolean _taken;
46 |
47 | protected static final String PHOTO_TAKEN = "photo_taken";
48 |
49 | @Override
50 | public void onCreate(Bundle savedInstanceState) {
51 | super.onCreate(savedInstanceState);
52 | setContentView(R.layout.main);
53 |
54 | String[] paths = new String[] { DATA_PATH, DATA_PATH + "tessdata/" };
55 |
56 | for (String path : paths) {
57 | File dir = new File(path);
58 | if (!dir.exists()) {
59 | if (!dir.mkdirs()) {
60 | Log.v(TAG, "ERROR: Creation of directory " + path + " on sdcard failed");
61 | return;
62 | } else {
63 | Log.v(TAG, "Created directory " + path + " on sdcard");
64 | }
65 | }
66 |
67 | }
68 |
69 | // lang.traineddata file with the app (in assets folder)
70 | // You can get them at:
71 | // http://code.google.com/p/tesseract-ocr/downloads/list
72 | // This area needs work and optimization
73 | if (!(new File(DATA_PATH + "tessdata/" + lang + ".traineddata")).exists()) {
74 | try {
75 |
76 | AssetManager assetManager = getAssets();
77 | InputStream in = assetManager.open("tessdata/" + lang + ".traineddata");
78 | //GZIPInputStream gin = new GZIPInputStream(in);
79 | OutputStream out = new FileOutputStream(DATA_PATH
80 | + "tessdata/" + lang + ".traineddata");
81 |
82 | // Transfer bytes from in to out
83 | byte[] buf = new byte[1024];
84 | int len;
85 | //while ((lenf = gin.read(buff)) > 0) {
86 | while ((len = in.read(buf)) > 0) {
87 | out.write(buf, 0, len);
88 | }
89 | in.close();
90 | //gin.close();
91 | out.close();
92 |
93 | Log.v(TAG, "Copied " + lang + " traineddata");
94 | } catch (IOException e) {
95 | Log.e(TAG, "Was unable to copy " + lang + " traineddata " + e.toString());
96 | }
97 | }
98 |
99 |
100 |
101 | // _image = (ImageView) findViewById(R.id.image);
102 | _field = (EditText) findViewById(R.id.field);
103 | _button = (Button) findViewById(R.id.button);
104 | _button.setOnClickListener(new ButtonClickHandler());
105 |
106 | _path = DATA_PATH + "/ocr.jpg";
107 | }
108 |
109 | public class ButtonClickHandler implements View.OnClickListener {
110 | public void onClick(View view) {
111 | Log.v(TAG, "Starting Camera app");
112 | startCameraActivity();
113 | }
114 | }
115 |
116 | // Simple android photo capture:
117 | // http://labs.makemachine.net/2010/03/simple-android-photo-capture/
118 |
119 | protected void startCameraActivity() {
120 | File file = new File(_path);
121 | Uri outputFileUri = Uri.fromFile(file);
122 |
123 | final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
124 | intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
125 |
126 | startActivityForResult(intent, 0);
127 | }
128 |
129 | @Override
130 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
131 |
132 | Log.i(TAG, "resultCode: " + resultCode);
133 |
134 | if (resultCode == -1) {
135 | onPhotoTaken();
136 | } else {
137 | Log.v(TAG, "User cancelled");
138 | }
139 | }
140 |
141 | @Override
142 | protected void onSaveInstanceState(Bundle outState) {
143 | outState.putBoolean(SimpleAndroidOCRActivity.PHOTO_TAKEN, _taken);
144 | }
145 |
146 | @Override
147 | protected void onRestoreInstanceState(Bundle savedInstanceState) {
148 | Log.i(TAG, "onRestoreInstanceState()");
149 | if (savedInstanceState.getBoolean(SimpleAndroidOCRActivity.PHOTO_TAKEN)) {
150 | onPhotoTaken();
151 | }
152 | }
153 |
154 | protected void onPhotoTaken() {
155 | _taken = true;
156 |
157 | BitmapFactory.Options options = new BitmapFactory.Options();
158 | options.inSampleSize = 4;
159 |
160 | Bitmap bitmap = BitmapFactory.decodeFile(_path, options);
161 |
162 | try {
163 | ExifInterface exif = new ExifInterface(_path);
164 | int exifOrientation = exif.getAttributeInt(
165 | ExifInterface.TAG_ORIENTATION,
166 | ExifInterface.ORIENTATION_NORMAL);
167 |
168 | Log.v(TAG, "Orient: " + exifOrientation);
169 |
170 | int rotate = 0;
171 |
172 | switch (exifOrientation) {
173 | case ExifInterface.ORIENTATION_ROTATE_90:
174 | rotate = 90;
175 | break;
176 | case ExifInterface.ORIENTATION_ROTATE_180:
177 | rotate = 180;
178 | break;
179 | case ExifInterface.ORIENTATION_ROTATE_270:
180 | rotate = 270;
181 | break;
182 | }
183 |
184 | Log.v(TAG, "Rotation: " + rotate);
185 |
186 | if (rotate != 0) {
187 |
188 | // Getting width & height of the given image.
189 | int w = bitmap.getWidth();
190 | int h = bitmap.getHeight();
191 |
192 | // Setting pre rotate
193 | Matrix mtx = new Matrix();
194 | mtx.preRotate(rotate);
195 |
196 | // Rotating Bitmap
197 | bitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, false);
198 | }
199 |
200 | // Convert to ARGB_8888, required by tess
201 | bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
202 |
203 | } catch (IOException e) {
204 | Log.e(TAG, "Couldn't correct orientation: " + e.toString());
205 | }
206 |
207 | // _image.setImageBitmap( bitmap );
208 |
209 | Log.v(TAG, "Before baseApi");
210 |
211 | TessBaseAPI baseApi = new TessBaseAPI();
212 | baseApi.setDebug(true);
213 | baseApi.init(DATA_PATH, lang);
214 | baseApi.setImage(bitmap);
215 |
216 | String recognizedText = baseApi.getUTF8Text();
217 |
218 | baseApi.end();
219 |
220 | // You now have the text in recognizedText var, you can do anything with it.
221 | // We will display a stripped out trimmed alpha-numeric version of it (if lang is eng)
222 | // so that garbage doesn't make it to the display.
223 |
224 | Log.v(TAG, "OCRED TEXT: " + recognizedText);
225 |
226 | if ( lang.equalsIgnoreCase("eng") ) {
227 | recognizedText = recognizedText.replaceAll("[^a-zA-Z0-9]+", " ");
228 | }
229 |
230 | recognizedText = recognizedText.trim();
231 |
232 | if ( recognizedText.length() != 0 ) {
233 | _field.setText(_field.getText().toString().length() == 0 ? recognizedText : _field.getText() + " " + recognizedText);
234 | _field.setSelection(_field.getText().toString().length());
235 | }
236 |
237 | // Cycle done.
238 | }
239 |
240 | // www.Gaut.am was here
241 | // Thanks for reading!
242 | }
243 |
--------------------------------------------------------------------------------