Skip to content

Commit c9b827e

Browse files
committed
refactor code
1 parent 5ceb6d4 commit c9b827e

File tree

2 files changed

+259
-50
lines changed

2 files changed

+259
-50
lines changed

app/src/main/java/io/github/subhamtyagi/ocr/MainActivity.java

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -239,19 +239,24 @@ public void startOCRFromShareMenu(Uri imageUri, Set<Language> languages) {
239239

240240
@SuppressWarnings("ResultOfMethodCallIgnored")
241241
private void initDirectories() {
242-
dirBest = new File(getExternalFilesDir("best").getAbsolutePath());
243-
dirFast = new File(getExternalFilesDir("fast").getAbsolutePath());
244-
dirStandard = new File(getExternalFilesDir("standard").getAbsolutePath());
245-
dirBest.mkdirs();
246-
dirStandard.mkdirs();
247-
dirFast.mkdirs();
248-
currentDirectory = new File(dirBest, "tessdata");
249-
currentDirectory.mkdirs();
250-
currentDirectory = new File(dirStandard, "tessdata");
251-
currentDirectory.mkdirs();
252-
currentDirectory = new File(dirFast, "tessdata");
253-
currentDirectory.mkdirs();
242+
String[] dirNames = {"best", "fast", "standard"};
243+
for (String dirName : dirNames) {
244+
File dir = new File(getExternalFilesDir(dirName), "tessdata");
245+
if (dir.mkdirs() || dir.isDirectory()) {
246+
// Directory was created or already exists
247+
// Optionally, you can set currentDirectory based on the specific directory
248+
if (dirName.equals("best")) {
249+
dirBest = dir.getParentFile();
250+
} else if (dirName.equals("fast")) {
251+
dirFast = dir.getParentFile();
252+
} else if (dirName.equals("standard")) {
253+
dirStandard = dir.getParentFile();
254+
}
255+
}
254256
}
257+
// Set currentDirectory to the last initialized directory (standard)
258+
currentDirectory = new File(dirStandard, "tessdata");
259+
}
255260

256261
/**
257262
* initialize the OCR i.e tesseract api
@@ -541,49 +546,51 @@ public void showOCRResult(String text) {
541546
* A Async Task to convert the image into text the return the text in String
542547
*/
543548
private class ConvertImageToTextTask extends AsyncTask<Bitmap, Void, String> {
549+
@Override
550+
protected void onPreExecute() {
551+
super.onPreExecute();
552+
mProgressIndicator.setProgress(0);
553+
mProgressIndicator.setVisibility(View.VISIBLE);
554+
animateImageViewAlpha(0.2f);
555+
}
544556

545-
@Override
546-
protected String doInBackground(Bitmap... bitmaps) {
547-
Bitmap bitmap = bitmaps[0];
548-
if (!isRefresh && Utils.isPreProcessImage()) {
549-
bitmap = Utils.preProcessBitmap(bitmap);
550-
// bitmap = Bitmap.createScaledBitmap(bitmap, (int) (bitmap.getWidth() * 1.5), (int) (bitmap.getHeight() * 1.5), true);
551-
}
552-
isRefresh = false;
553-
saveBitmapToStorage(bitmap);
554-
return mImageTextReader.getTextFromBitmap(bitmap);
555-
}
556-
557-
@Override
558-
protected void onPreExecute() {
559-
super.onPreExecute();
560-
mProgressIndicator.setProgress(0);
561-
mProgressIndicator.setVisibility(View.VISIBLE);
562-
mImageView.animate()
563-
.alpha(.2f)
564-
.setDuration(450)
565-
.start();
557+
@Override
558+
protected String doInBackground(Bitmap... bitmaps) {
559+
Bitmap bitmap = bitmaps[0];
560+
if (!isRefresh && Utils.isPreProcessImage()) {
561+
bitmap = Utils.preProcessBitmap(bitmap);
566562
}
563+
isRefresh = false;
564+
saveBitmapToStorage(bitmap);
565+
return mImageTextReader.getTextFromBitmap(bitmap);
566+
}
567567

568-
@Override
569-
protected void onPostExecute(String text) {
570-
mProgressIndicator.setVisibility(View.GONE);
571-
mImageView.animate()
572-
.alpha(1f)
573-
.setDuration(450)
574-
.start();
575-
String clean_text = Html.fromHtml(text).toString().trim();
576-
showOCRResult(clean_text);
577-
Toast.makeText(MainActivity.this, "With Confidence:" + mImageTextReader.getAccuracy() + "%", Toast.LENGTH_SHORT).show();
578-
579-
Utils.putLastUsedText(clean_text);
580-
Bitmap bitmap = loadBitmapFromStorage();
581-
if (bitmap != null) {
582-
mImageView.setImageBitmap(bitmap);
583-
}
568+
@Override
569+
protected void onPostExecute(String text) {
570+
mProgressIndicator.setVisibility(View.GONE);
571+
animateImageViewAlpha(1f);
572+
String cleanText = Html.fromHtml(text).toString().trim();
573+
showOCRResult(cleanText);
574+
Toast.makeText(MainActivity.this, "With Confidence: " + mImageTextReader.getAccuracy() + "%", Toast.LENGTH_SHORT).show();
575+
Utils.putLastUsedText(cleanText);
576+
updateImageView();
577+
}
578+
579+
private void animateImageViewAlpha(float alpha) {
580+
mImageView.animate()
581+
.alpha(alpha)
582+
.setDuration(450)
583+
.start();
584+
}
585+
586+
private void updateImageView() {
587+
Bitmap bitmap = loadBitmapFromStorage();
588+
if (bitmap != null) {
589+
mImageView.setImageBitmap(bitmap);
584590
}
585-
586591
}
592+
}
593+
587594

588595
/**
589596
* Download the training Data and save this to external storage
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
import android.os.Bundle;
2+
import android.graphics.Bitmap;
3+
import android.graphics.BitmapFactory;
4+
import android.net.Uri;
5+
import android.provider.MediaStore;
6+
import android.view.View;
7+
import android.widget.ImageView;
8+
import android.widget.Toast;
9+
10+
import androidx.annotation.NonNull;
11+
import androidx.annotation.Nullable;
12+
import androidx.appcompat.app.AlertDialog;
13+
import androidx.appcompat.app.AppCompatActivity;
14+
import androidx.lifecycle.Lifecycle;
15+
16+
import com.google.android.material.progressindicator.LinearProgressIndicator;
17+
import com.googlecode.tesseract.android.TessBaseAPI;
18+
import com.theartofdev.edmodo.cropper.CropImage;
19+
20+
import java.io.BufferedInputStream;
21+
import java.io.File;
22+
import java.io.FileOutputStream;
23+
import java.io.IOException;
24+
import java.io.InputStream;
25+
import java.io.OutputStream;
26+
import java.net.HttpURLConnection;
27+
import java.net.URL;
28+
import java.util.Set;
29+
import java.util.concurrent.ExecutorService;
30+
import java.util.concurrent.Executors;
31+
32+
public class MainActivity extends AppCompatActivity implements TessBaseAPI.ProgressNotifier {
33+
34+
private ImageView mImageView;
35+
private LinearProgressIndicator mProgressIndicator;
36+
private ImageTextReader mImageTextReader;
37+
private ExecutorService executorService;
38+
private AlertDialog dialog;
39+
private File currentDirectory;
40+
41+
@Override
42+
protected void onCreate(Bundle savedInstanceState) {
43+
super.onCreate(savedInstanceState);
44+
setContentView(R.layout.activity_main);
45+
46+
mImageView = findViewById(R.id.source_image);
47+
mProgressIndicator = findViewById(R.id.progress_indicator);
48+
49+
executorService = Executors.newFixedThreadPool(2); // Initialize the executor
50+
initializeOCR();
51+
}
52+
53+
private void initializeOCR() {
54+
executorService.submit(() -> {
55+
// Initialize OCR components (assuming this method initializes the OCR engine)
56+
Set<Language> languages = Utils.getTrainingDataLanguages(this);
57+
mImageTextReader = ImageTextReader.getInstance(
58+
currentDirectory.getAbsolutePath(),
59+
languages,
60+
Utils.getPageSegMode(),
61+
Utils.getAllParameters(),
62+
Utils.isExtraParameterSet(),
63+
MainActivity.this
64+
);
65+
});
66+
}
67+
68+
private void convertImageToText(Uri imageUri) {
69+
Bitmap bitmap = null;
70+
try {
71+
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
72+
} catch (IOException e) {
73+
e.printStackTrace();
74+
}
75+
76+
mImageView.setImageURI(imageUri);
77+
78+
// Use ExecutorService for background tasks
79+
executorService.submit(() -> {
80+
if (bitmap != null) {
81+
saveBitmapToStorage(bitmap);
82+
String resultText = mImageTextReader.getTextFromBitmap(bitmap);
83+
runOnUiThread(() -> onOCRCompleted(resultText));
84+
}
85+
});
86+
}
87+
88+
private void onOCRCompleted(String text) {
89+
mProgressIndicator.setVisibility(View.GONE);
90+
String cleanText = text.trim(); // Removed HTML processing for simplicity
91+
showOCRResult(cleanText);
92+
Toast.makeText(MainActivity.this, "OCR Completed", Toast.LENGTH_SHORT).show();
93+
}
94+
95+
private void showOCRResult(String text) {
96+
if (this.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) {
97+
// BottomSheet to show results
98+
BottomSheetResultsFragment bottomSheetResultsFragment = BottomSheetResultsFragment.newInstance(text);
99+
bottomSheetResultsFragment.show(getSupportFragmentManager(), "bottomSheetResultsFragment");
100+
}
101+
}
102+
103+
public void saveBitmapToStorage(Bitmap bitmap) {
104+
try (FileOutputStream fileOutputStream = openFileOutput("last_file.jpeg", MODE_PRIVATE)) {
105+
bitmap.compress(Bitmap.CompressFormat.JPEG, 30, fileOutputStream);
106+
} catch (IOException e) {
107+
e.printStackTrace();
108+
}
109+
}
110+
111+
@Override
112+
protected void onDestroy() {
113+
super.onDestroy();
114+
if (executorService != null) {
115+
executorService.shutdown();
116+
}
117+
}
118+
119+
@Override
120+
public void onProgressValues(TessBaseAPI.ProgressValues progressValues) {
121+
runOnUiThread(() -> mProgressIndicator.setProgress((int) (progressValues.getPercent() * 1.46)));
122+
}
123+
124+
// Method to handle language data download
125+
private void downloadLanguageData(final String dataType, Set<Language> languages) {
126+
for (Language language : languages) {
127+
if (languageDataMissing(dataType, language)) {
128+
dialog = new AlertDialog.Builder(this)
129+
.setTitle(R.string.training_data_missing)
130+
.setMessage("Downloading " + language.getName() + " data...")
131+
.setPositiveButton(R.string.yes, (dialog, which) -> {
132+
// Submit to Executor for background download
133+
executorService.submit(() -> downloadTrainingData(dataType, language.getCode()));
134+
})
135+
.setNegativeButton(R.string.no, (dialog, which) -> dialog.cancel())
136+
.create();
137+
dialog.show();
138+
}
139+
}
140+
}
141+
142+
private boolean downloadTrainingData(String dataType, String lang) {
143+
String downloadURL = getDownloadUrl(dataType, lang);
144+
try {
145+
URL url = new URL(downloadURL);
146+
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
147+
conn.connect();
148+
149+
int totalContentSize = conn.getContentLength();
150+
if (totalContentSize <= 0) return false;
151+
152+
try (InputStream input = new BufferedInputStream(conn.getInputStream());
153+
OutputStream output = new FileOutputStream(new File(currentDirectory, String.format(Constants.LANGUAGE_CODE, lang)))) {
154+
byte[] data = new byte[6 * 1024];
155+
int count;
156+
while ((count = input.read(data)) != -1) {
157+
output.write(data, 0, count);
158+
}
159+
}
160+
return true;
161+
} catch (IOException e) {
162+
e.printStackTrace();
163+
return false;
164+
}
165+
}
166+
167+
private String getDownloadUrl(String dataType, String lang) {
168+
switch (dataType) {
169+
case "best":
170+
return String.format(Constants.TESSERACT_DATA_DOWNLOAD_URL_BEST, lang);
171+
case "standard":
172+
return String.format(Constants.TESSERACT_DATA_DOWNLOAD_URL_STANDARD, lang);
173+
default:
174+
return String.format(Constants.TESSERACT_DATA_DOWNLOAD_URL_FAST, lang);
175+
}
176+
}
177+
178+
private boolean languageDataMissing(@NonNull String dataType, @NonNull Language language) {
179+
switch (dataType) {
180+
case "best":
181+
currentDirectory = new File(getExternalFilesDir("best"), "tessdata");
182+
break;
183+
case "standard":
184+
currentDirectory = new File(getExternalFilesDir("standard"), "tessdata");
185+
break;
186+
default:
187+
currentDirectory = new File(getExternalFilesDir("fast"), "tessdata");
188+
}
189+
return !new File(currentDirectory, String.format(Constants.LANGUAGE_CODE, language.getCode())).exists();
190+
}
191+
192+
// Result handling after image crop
193+
@Override
194+
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
195+
super.onActivityResult(requestCode, resultCode, data);
196+
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) {
197+
Uri resultUri = CropImage.getActivityResult(data).getUri();
198+
convertImageToText(resultUri);
199+
}
200+
}
201+
}
202+

0 commit comments

Comments
 (0)