/*
* Copyright (C) 2008 ZXing authors
* Copyright 2011 Robert Theis
*
* 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.
*/
package com.moob.ocrdnitest;
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.ClipboardManager;
import android.text.SpannableStringBuilder;
import android.text.style.CharacterStyle;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.googlecode.tesseract.android.TessBaseAPI;
import edu.sfsu.cs.orange.ocr.camera.CameraManager;
import edu.sfsu.cs.orange.ocr.language.LanguageCodeHelper;
/**
* This activity opens the camera and does the actual scanning on a background thread. It draws a
* viewfinder to help the user place the barcode correctly, shows feedback as the image processing
* is happening, and then overlays the results when a scan is successful.
*
* The code for this class was adapted from the ZXing project: http://code.google.com/p/zxing/
*/
public final class CaptureActivity extends Activity implements SurfaceHolder.Callback
{
private static final String TAG = CaptureActivity.class.getSimpleName();
// Note: These constants will be overridden by any default values defined in preferences.xml.
/** ISO 639-3 language code indicating the default recognition language. */
public static final String DEFAULT_SOURCE_LANGUAGE_CODE = "spa";
/** ISO 639-1 language code indicating the default target language for translation. */
public static final String DEFAULT_TARGET_LANGUAGE_CODE = "es";
/** The default online machine translation service to use. */
public static final String DEFAULT_TRANSLATOR = "Bing Translator";
/** The default OCR engine to use. */
public static final String DEFAULT_OCR_ENGINE_MODE = "Tesseract";
/** The default page segmentation mode to use. */
public static final String DEFAULT_PAGE_SEGMENTATION_MODE = "Auto";
/** Whether to use autofocus by default. */
public static final boolean DEFAULT_TOGGLE_AUTO_FOCUS = true;
/** Whether to beep by default when the shutter button is pressed. */
public static final boolean DEFAULT_TOGGLE_BEEP = true;
/** Whether to initially show a looping, real-time OCR display. */
public static final boolean DEFAULT_TOGGLE_CONTINUOUS = true;
/** Whether to initially reverse the image returned by the camera. */
public static final boolean DEFAULT_TOGGLE_REVERSED_IMAGE = false;
/** Whether to enable the use of online translation services be default. */
public static final boolean DEFAULT_TOGGLE_TRANSLATION = false;
/** Whether the light should be initially activated by default. */
public static final boolean DEFAULT_TOGGLE_LIGHT = false;
/** Flag to display the real-time recognition results at the top of the scanning screen. */
private static final boolean CONTINUOUS_DISPLAY_RECOGNIZED_TEXT = true;
/** Flag to display recognition-related statistics on the scanning screen. */
private static final boolean CONTINUOUS_DISPLAY_METADATA = true;
/** Flag to enable display of the on-screen shutter button. */
private static final boolean DISPLAY_SHUTTER_BUTTON = true;
/** Languages for which Cube data is available. */
static final String[] CUBE_SUPPORTED_LANGUAGES = {
"ara", // Arabic
"eng", // English
"hin" // Hindi
};
private Timer myTimer;
/** Languages that require Cube, and cannot run using Tesseract. */
private static final String[] CUBE_REQUIRED_LANGUAGES = {
"ara" // Arabic
};
/** Resource to use for data file downloads. */
static final String DOWNLOAD_BASE = "http://tesseract-ocr.googlecode.com/files/";
/** Download filename for orientation and script detection (OSD) data. */
static final String OSD_FILENAME = "tesseract-ocr-3.01.osd.tar";
/** Destination filename for orientation and script detection (OSD) data. */
static final String OSD_FILENAME_BASE = "osd.traineddata";
/** Minimum mean confidence score necessary to not reject single-shot OCR result. Currently unused. */
static final int MINIMUM_MEAN_CONFIDENCE = 65; // 0 means don't reject any scored results
// Context menu
private static final int SETTINGS_ID = Menu.FIRST;
private static final int ABOUT_ID = Menu.FIRST + 1;
// Options menu, for copy to clipboard
private static final int OPTIONS_COPY_RECOGNIZED_TEXT_ID = Menu.FIRST;
private static final int OPTIONS_COPY_TRANSLATED_TEXT_ID = Menu.FIRST + 1;
private static final int OPTIONS_SHARE_RECOGNIZED_TEXT_ID = Menu.FIRST + 2;
private static final int OPTIONS_SHARE_TRANSLATED_TEXT_ID = Menu.FIRST + 3;
private CameraManager cameraManager;
private CaptureActivityHandler handler;
private ViewfinderView viewfinderView;
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private TextView statusViewBottom;
private TextView statusViewTop;
private Button btnShare;
private Button btnrescan;
private TextView ocrResultView;
private TextView translationView;
private View cameraButtonView;
private View resultView;
private View progressView;
private OcrResult lastResult;
private Bitmap lastBitmap;
public int restante;
private boolean hasSurface;
private BeepManager beepManager;
private TessBaseAPI baseApi; // Java interface for the Tesseract OCR engine
private String sourceLanguageCodeOcr; // ISO 639-3 language code
private String sourceLanguageReadable; // Language name, for example, "English"
private String targetLanguageReadable; // Language name, for example, "English"
private int pageSegmentationMode = TessBaseAPI.PSM_AUTO;
private int ocrEngineMode = TessBaseAPI.OEM_TESSERACT_ONLY;
private String characterBlacklist;
private String characterWhitelist;
// private ToggleButton torchButton;
private boolean isTranslationActive; // Whether we want to show translations
private boolean isContinuousModeActive; // Whether we are doing OCR in continuous mode
private SharedPreferences prefs;
private OnSharedPreferenceChangeListener listener;
private ProgressDialog dialog; // for initOcr - language download & unzip
private ProgressDialog indeterminateDialog; // also for initOcr - init OCR engine
private boolean isEngineReady;
private boolean isPaused;
private static boolean isFirstLaunch; // True if this is the first time the app is being run
private String resultado;
Handler getHandler() {
return handler;
}
TessBaseAPI getBaseApi() {
return baseApi;
}
CameraManager getCameraManager() {
return cameraManager;
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
restante=5;
resultado="";
checkFirstLaunch();
if (isFirstLaunch) {
setDefaultPreferences();
}
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.capture);
viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
cameraButtonView = findViewById(R.id.camera_button_view);
resultView = findViewById(R.id.result_view);
viewfinderView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("TEXT:", "autofocus???");
if ((!isPaused)&&(isContinuousModeActive)&&(isEngineReady))
{
Log.d("TEXT:", "Yes please?");
requestDelayedAutoFocus();
}
}
});
statusViewBottom = (TextView) findViewById(R.id.status_view_bottom);
registerForContextMenu(statusViewBottom);
statusViewTop = (TextView) findViewById(R.id.status_view_top);
registerForContextMenu(statusViewTop);
btnShare=(Button)findViewById(R.id.btn_share);
btnrescan=(Button)findViewById(R.id.btn_rescan);
handler = null;
lastResult = null;
hasSurface = false;
beepManager = new BeepManager(this);
// Camera shutter button
btnShare.setVisibility(View.GONE);
btnrescan.setVisibility(View.GONE);
ocrResultView = (TextView) findViewById(R.id.ocr_result_text_view);
registerForContextMenu(ocrResultView);
translationView = (TextView) findViewById(R.id.translation_text_view);
registerForContextMenu(translationView);
progressView = (View) findViewById(R.id.indeterminate_progress_indicator_view);
cameraManager = new CameraManager(getApplication());
viewfinderView.setCameraManager(cameraManager);
isEngineReady = false;
}
public void shareDatos(View target)
{
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("text/plain");
share.putExtra(Intent.EXTRA_TEXT,resultado);
startActivity(Intent.createChooser(share, "Compartir datos"));
}
public void reScan(View target)
{
btnShare.setVisibility(View.GONE);
btnrescan.setVisibility(View.GONE);
resumeOCR();
resumeContinuousDecoding();
}
@Override
protected void onResume() {
super.onResume();
resetStatusView();
String previousSourceLanguageCodeOcr = sourceLanguageCodeOcr;
int previousOcrEngineMode = ocrEngineMode;
retrievePreferences();
// Set up the camera preview surface.
surfaceView = (SurfaceView) findViewById(R.id.preview_view);
surfaceHolder = surfaceView.getHolder();
if (!hasSurface) {
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
// Comment out the following block to test non-OCR functions without an SD card
// Do OCR engine initialization, if necessary
boolean doNewInit = (baseApi == null) || !sourceLanguageCodeOcr.equals(previousSourceLanguageCodeOcr) ||
ocrEngineMode != previousOcrEngineMode;
if (doNewInit) {
// Initialize the OCR engine
File storageDirectory = getStorageDirectory();
if (storageDirectory != null) {
initOcrEngine(storageDirectory, sourceLanguageCodeOcr, sourceLanguageReadable);
}
} else {
// We already have the engine initialized, so just start the camera.
resumeOCR();
}
}
/**
* Method to start or restart recognition after the OCR engine has been initialized,
* or after the app regains focus. Sets state related settings and OCR engine parameters,
* and requests camera initialization.
*/
void resumeOCR() {
Log.d(TAG, "resumeOCR()");
// This method is called when Tesseract has already been successfully initialized, so set
// isEngineReady = true here.
isEngineReady = true;
// viewfinderView.removeResultText();
isPaused = false;
if (handler != null) {
handler.resetState();
}
if (baseApi != null) {
baseApi.setPageSegMode(pageSegmentationMode);
//TODO configurar caracteres
baseApi.setVariable(TessBaseAPI.VAR_CHAR_BLACKLIST, characterBlacklist);
baseApi.setVariable(TessBaseAPI.VAR_CHAR_WHITELIST, characterWhitelist);
}
if (hasSurface) {
// The activity was paused but not stopped, so the surface still exists. Therefore
// surfaceCreated() won't be called, so init the camera here.
initCamera(surfaceHolder);
}
}
/** Called when the shutter button is pressed in continuous mode. */
void onShutterButtonPressContinuous() {
isPaused = true;
handler.stop();
// beepManager.playBeepSoundAndVibrate();
if (lastResult != null) {
//re handleOcrDecode(lastResult);
} else {
Toast toast = Toast.makeText(this, "OCR failed. Please try again.", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP, 0, 0);
toast.show();
resumeContinuousDecoding();
}
}
/** Called to resume recognition after translation in continuous mode. */
@SuppressWarnings("unused")
void resumeContinuousDecoding() {
isPaused = false;
resetStatusView();
setStatusViewForContinuous();
DecodeHandler.resetDecodeState();
handler.resetState();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "surfaceCreated()");
if (holder == null) {
Log.e(TAG, "surfaceCreated gave us a null surface");
}
// Only initialize the camera if the OCR engine is ready to go.
if (!hasSurface && isEngineReady) {
Log.d(TAG, "surfaceCreated(): calling initCamera()...");
initCamera(holder);
}
hasSurface = true;
}
/** Initializes the camera and starts the handler to begin previewing. */
private void initCamera(SurfaceHolder surfaceHolder) {
Log.d(TAG, "initCamera()");
if (surfaceHolder == null) {
throw new IllegalStateException("No SurfaceHolder provided");
}
try {
// Open and initialize the camera
cameraManager.openDriver(surfaceHolder);
// Creating the handler starts the preview, which can also throw a RuntimeException.
handler = new CaptureActivityHandler(this, cameraManager, isContinuousModeActive);
} catch (IOException ioe) {
showErrorMessage("Error", "Could not initialize camera. Please try restarting device.");
} catch (RuntimeException e) {
// Barcode Scanner has seen crashes in the wild of this variety:
// java.?lang.?RuntimeException: Fail to connect to camera service
showErrorMessage("Error", "Could not initialize camera. Please try restarting device.");
}
}
@Override
protected void onPause() {
if (handler != null) {
handler.quitSynchronously();
}
// Stop using the camera, to avoid conflicting with other camera-based apps
cameraManager.closeDriver();
if (!hasSurface) {
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
surfaceHolder.removeCallback(this);
}
super.onPause();
}
void stopHandler() {
if (handler != null) {
handler.stop();
}
}
@Override
protected void onDestroy() {
if (baseApi != null) {
baseApi.end();
}
super.onDestroy();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// First check if we're paused in continuous mode, and if so, just unpause.
if (isPaused) {
Log.d(TAG, "only resuming continuous recognition, not quitting...");
resumeContinuousDecoding();
return true;
}
// Exit the app if we're not viewing an OCR result.
if (lastResult == null) {
setResult(RESULT_CANCELED);
finish();
return true;
} else {
// Go back to previewing in regular OCR mode.
resetStatusView();
if (handler != null) {
handler.sendEmptyMessage(R.id.restart_preview);
}
return true;
}
} else if (keyCode == KeyEvent.KEYCODE_CAMERA) {
if (isContinuousModeActive) {
onShutterButtonPressContinuous();
} else {
handler.hardwareShutterButtonClick();
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_FOCUS) {
// Only perform autofocus if user is not holding down the button.
if (event.getRepeatCount() == 0) {
cameraManager.requestAutoFocus(500L);
}
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// MenuInflater inflater = getMenuInflater();
// inflater.inflate(R.menu.options_menu, menu);
super.onCreateOptionsMenu(menu);
// menu.add(0, SETTINGS_ID, 0, "Settings").setIcon(android.R.drawable.ic_menu_preferences);
// menu.add(0, ABOUT_ID, 0, "About").setIcon(android.R.drawable.ic_menu_info_details);
return false;
}
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
/** Sets the necessary language code values for the given OCR language. */
private boolean setSourceLanguage(String languageCode) {
sourceLanguageCodeOcr = languageCode;
// sourceLanguageCodeTranslation = LanguageCodeHelper.mapLanguageCode(languageCode);
sourceLanguageReadable = LanguageCodeHelper.getOcrLanguageName(this, languageCode);
return true;
}
/** Sets the necessary language code values for the translation target language. */
private boolean setTargetLanguage(String languageCode) {
// targetLanguageCodeTranslation = languageCode;
targetLanguageReadable = LanguageCodeHelper.getTranslationLanguageName(this, languageCode);
return true;
}
/** Finds the proper location on the SD card where we can save files. */
private File getStorageDirectory() {
//Log.d(TAG, "getStorageDirectory(): API level is " + Integer.valueOf(android.os.Build.VERSION.SDK_INT));
String state = null;
try {
state = Environment.getExternalStorageState();
} catch (RuntimeException e) {
Log.e(TAG, "Is the SD card visible?", e);
showErrorMessage("Error", "Required external storage (such as an SD card) is unavailable.");
}
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
// We can read and write the media
// if (Integer.valueOf(android.os.Build.VERSION.SDK_INT) > 7) {
// For Android 2.2 and above
try {
return getExternalFilesDir(Environment.MEDIA_MOUNTED);
} catch (NullPointerException e) {
// We get an error here if the SD card is visible, but full
Log.e(TAG, "External storage is unavailable");
showErrorMessage("Error", "Required external storage (such as an SD card) is full or unavailable.");
}
// } else {
// // For Android 2.1 and below, explicitly give the path as, for example,
// // "/mnt/sdcard/Android/data/edu.sfsu.cs.orange.ocr/files/"
// return new File(Environment.getExternalStorageDirectory().toString() + File.separator +
// "Android" + File.separator + "data" + File.separator + getPackageName() +
// File.separator + "files" + File.separator);
// }
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
Log.e(TAG, "External storage is read-only");
showErrorMessage("Error", "Required external storage (such as an SD card) is unavailable for data storage.");
} else {
// Something else is wrong. It may be one of many other states, but all we need
// to know is we can neither read nor write
Log.e(TAG, "External storage is unavailable");
showErrorMessage("Error", "Required external storage (such as an SD card) is unavailable or corrupted.");
}
return null;
}
/**
* Requests initialization of the OCR engine with the given parameters.
*
* @param storageRoot Path to location of the tessdata directory to use
* @param languageCode Three-letter ISO 639-3 language code for OCR
* @param languageName Name of the language for OCR, for example, "English"
*/
private void initOcrEngine(File storageRoot, String languageCode, String languageName) {
isEngineReady = false;
// Set up the dialog box for the thermometer-style download progress indicator
if (dialog != null) {
dialog.dismiss();
}
dialog = new ProgressDialog(this);
// If we have a language that only runs using Cube, then set the ocrEngineMode to Cube
if (ocrEngineMode != TessBaseAPI.OEM_CUBE_ONLY) {
for (String s : CUBE_REQUIRED_LANGUAGES) {
if (s.equals(languageCode)) {
ocrEngineMode = TessBaseAPI.OEM_CUBE_ONLY;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().putString(PreferencesActivity.KEY_OCR_ENGINE_MODE, getOcrEngineModeName()).commit();
}
}
}
// If our language doesn't support Cube, then set the ocrEngineMode to Tesseract
if (ocrEngineMode != TessBaseAPI.OEM_TESSERACT_ONLY) {
boolean cubeOk = false;
for (String s : CUBE_SUPPORTED_LANGUAGES) {
if (s.equals(languageCode)) {
cubeOk = true;
}
}
if (!cubeOk) {
ocrEngineMode = TessBaseAPI.OEM_TESSERACT_ONLY;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().putString(PreferencesActivity.KEY_OCR_ENGINE_MODE, getOcrEngineModeName()).commit();
}
}
// Display the name of the OCR engine we're initializing in the indeterminate progress dialog box
indeterminateDialog = new ProgressDialog(this);
indeterminateDialog.setTitle("Please wait");
String ocrEngineModeName = getOcrEngineModeName();
if (ocrEngineModeName.equals("Both")) {
indeterminateDialog.setMessage("Initializing Cube and Tesseract OCR engines for " + languageName + "...");
} else {
indeterminateDialog.setMessage("Initializing " + ocrEngineModeName + " OCR engine for " + languageName + "...");
}
indeterminateDialog.setCancelable(false);
indeterminateDialog.show();
if (handler != null) {
handler.quitSynchronously();
}
// Disable continuous mode if we're using Cube. This will prevent bad states for devices
// with low memory that crash when running OCR with Cube, and prevent unwanted delays.
if (ocrEngineMode == TessBaseAPI.OEM_CUBE_ONLY || ocrEngineMode == TessBaseAPI.OEM_TESSERACT_CUBE_COMBINED) {
Log.d(TAG, "Disabling continuous preview");
isContinuousModeActive = false;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().putBoolean(PreferencesActivity.KEY_CONTINUOUS_PREVIEW, true);
}
// Start AsyncTask to install language data and init OCR
baseApi = new TessBaseAPI();
new OcrInitAsyncTask(this, baseApi, dialog, indeterminateDialog, languageCode, languageName, ocrEngineMode)
.execute(storageRoot.toString());
}
/**
* Displays information relating to the result of OCR, and requests a translation if necessary.
*
* @param ocrResult Object representing successful OCR results
* @return True if a non-null result was received for OCR
*/
boolean handleOcrDecode(OcrResult ocrResult) {
lastResult = ocrResult;
Log.d("TEXT:", "OCR:"+String.valueOf(ocrResult.getMeanConfidence())+"-->"+ocrResult.getText());
// Test whether the result is null
if (ocrResult.getText() == null || ocrResult.getText().equals("")) {
Toast toast = Toast.makeText(this, "OCR failed. Please try again.", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP, 0, 0);
toast.show();
return false;
}
// Turn off capture-related UI elements
statusViewBottom.setVisibility(View.GONE);
statusViewTop.setVisibility(View.GONE);
cameraButtonView.setVisibility(View.GONE);
viewfinderView.setVisibility(View.GONE);
resultView.setVisibility(View.VISIBLE);
ImageView bitmapImageView = (ImageView) findViewById(R.id.image_view);
lastBitmap = ocrResult.getBitmap();
if (lastBitmap == null) {
bitmapImageView.setImageBitmap(BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher));
} else {
bitmapImageView.setImageBitmap(lastBitmap);
}
// Display the recognized text
TextView sourceLanguageTextView = (TextView) findViewById(R.id.source_language_text_view);
sourceLanguageTextView.setText(sourceLanguageReadable);
TextView ocrResultTextView = (TextView) findViewById(R.id.ocr_result_text_view);
ocrResultTextView.setText(ocrResult.getText());
// Crudely scale betweeen 22 and 32 -- bigger font for shorter text
int scaledSize = Math.max(22, 32 - ocrResult.getText().length() / 4);
ocrResultTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, scaledSize);
TextView translationLanguageLabelTextView = (TextView) findViewById(R.id.translation_language_label_text_view);
TextView translationLanguageTextView = (TextView) findViewById(R.id.translation_language_text_view);
TextView translationTextView = (TextView) findViewById(R.id.translation_text_view);
if (isTranslationActive) {
// Handle translation text fields
translationLanguageLabelTextView.setVisibility(View.GONE);
translationLanguageTextView.setText(targetLanguageReadable);
translationLanguageTextView.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL), Typeface.NORMAL);
translationLanguageTextView.setVisibility(View.VISIBLE);
// Activate/re-activate the indeterminate progress indicator
translationTextView.setVisibility(View.GONE);
progressView.setVisibility(View.VISIBLE);
setProgressBarVisibility(true);
// Get the translation asynchronously
/* new TranslateAsyncTask(this, sourceLanguageCodeTranslation, targetLanguageCodeTranslation,
ocrResult.getText()).execute();*/
} else {
translationLanguageLabelTextView.setVisibility(View.GONE);
translationLanguageTextView.setVisibility(View.GONE);
translationTextView.setVisibility(View.GONE);
progressView.setVisibility(View.GONE);
setProgressBarVisibility(false);
}
return true;
}
/**
* Displays information relating to the results of a successful real-time OCR request.
*
* @param ocrResult Object representing successful OCR results
*/
void handleOcrContinuousDecode(OcrResult ocrResult) {
lastResult = ocrResult;
// Send an OcrResultText object to the ViewfinderView for text rendering
viewfinderView.addResultText(new OcrResultText(ocrResult.getText(),
ocrResult.getWordConfidences(),
ocrResult.getMeanConfidence(),
ocrResult.getBitmapDimensions(),
ocrResult.getRegionBoundingBoxes(),
ocrResult.getTextlineBoundingBoxes(),
ocrResult.getStripBoundingBoxes(),
ocrResult.getWordBoundingBoxes(),
ocrResult.getCharacterBoundingBoxes()));
btnShare.setVisibility(View.GONE);
btnrescan.setVisibility(View.GONE);
Integer meanConfidence = ocrResult.getMeanConfidence();
Log.d("TEXT:", "Confianza:"+String.valueOf(meanConfidence)+"Lineas:"+String.valueOf(ocrResult.getText().split("\r\n|\r|\n").length));
Log.d("TEXT:", "TXT"+ocrResult.getText());
if ((meanConfidence>MINIMUM_MEAN_CONFIDENCE)&&(ocrResult.getText().split("\r\n|\r|\n").length==3))
{
if (CONTINUOUS_DISPLAY_RECOGNIZED_TEXT) {
// Display the recognized text on the screen
statusViewTop.setText(ocrResult.getText());
resultado=ocrResult.getText();
int scaledSize = Math.max(22, 32 - ocrResult.getText().length() / 4);
statusViewTop.setTextSize(TypedValue.COMPLEX_UNIT_SP, scaledSize);
statusViewTop.setTextColor(Color.BLACK);
statusViewTop.setBackgroundResource(R.color.status_top_text_background);
statusViewTop.getBackground().setAlpha(meanConfidence * (255 / 100));
btnShare.setVisibility(View.VISIBLE);
btnrescan.setVisibility(View.VISIBLE);
onShutterButtonPressContinuous();
}
if (CONTINUOUS_DISPLAY_METADATA) {
// Display recognition-related metadata at the bottom of the screen
stopTimer();
long recognitionTimeRequired = ocrResult.getRecognitionTimeRequired();
Log.d("TEXT:", "datos leidos!!");
statusViewBottom.setTextSize(14);
//if estan puestos los cuadrados
String s="Leidos Datos con un " +
meanConfidence.toString() + "% de acierto. Usados " + recognitionTimeRequired + " ms";
statusViewBottom.setText(s);
}
}else{
startTimer();
}
}
public void startTimer()
{
restante=5;
String s="TEXTO ENCONTRADO MANTENGA EL TELEFONO "+String.valueOf(restante)+" SEGUNDOS...";
Log.d("TEXT:", "startTimer");
statusViewBottom.setText(s);
if (myTimer!=null){
myTimer.cancel();
myTimer=null;
}
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
@Override
public void run() {
timerFunction();
}
}, 0, 1000);
}
public void timerFunction()
{
Log.d("TEXT:", "Clicking");
runOnUiThread(new Runnable() {
public void run() {
restante=restante-1;
if (restante!=0){
String s="TEXTO ENCONTRADO MANTENGA EL TELEFONO "+String.valueOf(restante)+" SEGUNDOS...";
statusViewBottom.setText(s);
}else
{
restante=5;
String s="Probando de nuevo, vuelva a acercar el terminal e intente no moverlo";
statusViewBottom.setText(s);
}
}
});
}
public void stopTimer()
{
if (myTimer!=null)
{
Log.d("TEXT:", "stopTimer");
myTimer.cancel();
}
}
/**
* Version of handleOcrContinuousDecode for failed OCR requests. Displays a failure message.
*
* @param obj Metadata for the failed OCR request.
*/
void handleOcrContinuousDecode(OcrResultFailure obj) {
lastResult = null;
viewfinderView.removeResultText();
// Reset the text in the recognized text box.
statusViewTop.setText("");
btnShare.setVisibility(View.GONE);
btnrescan.setVisibility(View.GONE);
if (CONTINUOUS_DISPLAY_METADATA) {
// Color text delimited by '-' as red.
statusViewBottom.setTextSize(14);
String s="No se ha encontrado texto, Acerque el movil y mantenga unos segundos. Aparecer�n unos recuadros en el texto, despu�s espere unos 5 segundos";
statusViewBottom.setText(s);
stopTimer();
}
}
/**
* Given either a Spannable String or a regular String and a token, apply
* the given CharacterStyle to the span between the tokens.
*
* NOTE: This method was adapted from:
* http://www.androidengineer.com/2010/08/easy-method-for-formatting-android.html
*
* <p>
* For example, {@code setSpanBetweenTokens("Hello ##world##!", "##", new
* ForegroundColorSpan(0xFFFF0000));} will return a CharSequence {@code
* "Hello world!"} with {@code world} in red.
*
*/
private CharSequence setSpanBetweenTokens(CharSequence text, String token,
CharacterStyle... cs) {
// Start and end refer to the points where the span will apply
int tokenLen = token.length();
int start = text.toString().indexOf(token) + tokenLen;
int end = text.toString().indexOf(token, start);
if (start > -1 && end > -1) {
// Copy the spannable string to a mutable spannable string
SpannableStringBuilder ssb = new SpannableStringBuilder(text);
for (CharacterStyle c : cs)
ssb.setSpan(c, start, end, 0);
text = ssb;
}
return text;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
if (v.equals(ocrResultView)) {
menu.add(Menu.NONE, OPTIONS_COPY_RECOGNIZED_TEXT_ID, Menu.NONE, "Copy recognized text");
menu.add(Menu.NONE, OPTIONS_SHARE_RECOGNIZED_TEXT_ID, Menu.NONE, "Share recognized text");
} else if (v.equals(translationView)){
menu.add(Menu.NONE, OPTIONS_COPY_TRANSLATED_TEXT_ID, Menu.NONE, "Copy translated text");
menu.add(Menu.NONE, OPTIONS_SHARE_TRANSLATED_TEXT_ID, Menu.NONE, "Share translated text");
}
}
@Override
public boolean onContextItemSelected(MenuItem item) {
ClipboardManager clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
switch (item.getItemId()) {
case OPTIONS_COPY_RECOGNIZED_TEXT_ID:
clipboardManager.setText(ocrResultView.getText());
if (clipboardManager.hasText()) {
Toast toast = Toast.makeText(this, "Text copied.", Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM, 0, 0);
toast.show();
}
return true;
case OPTIONS_SHARE_RECOGNIZED_TEXT_ID:
Intent shareRecognizedTextIntent = new Intent(android.content.Intent.ACTION_SEND);
shareRecognizedTextIntent.setType("text/plain");
shareRecognizedTextIntent.putExtra(android.content.Intent.EXTRA_TEXT, ocrResultView.getText());
startActivity(Intent.createChooser(shareRecognizedTextIntent, "Share via"));
return true;
case OPTIONS_COPY_TRANSLATED_TEXT_ID:
clipboardManager.setText(translationView.getText());
if (clipboardManager.hasText()) {
Toast toast = Toast.makeText(this, "Text copied.", Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM, 0, 0);
toast.show();
}
return true;
case OPTIONS_SHARE_TRANSLATED_TEXT_ID:
Intent shareTranslatedTextIntent = new Intent(android.content.Intent.ACTION_SEND);
shareTranslatedTextIntent.setType("text/plain");
shareTranslatedTextIntent.putExtra(android.content.Intent.EXTRA_TEXT, translationView.getText());
startActivity(Intent.createChooser(shareTranslatedTextIntent, "Share via"));
return true;
default:
return super.onContextItemSelected(item);
}
}
/**
* Resets view elements.
*/
private void resetStatusView() {
resultView.setVisibility(View.GONE);
if (CONTINUOUS_DISPLAY_METADATA) {
statusViewBottom.setText("");
statusViewBottom.setTextSize(14);
statusViewBottom.setTextColor(getResources().getColor(R.color.status_text));
statusViewBottom.setVisibility(View.VISIBLE);
}
if (CONTINUOUS_DISPLAY_RECOGNIZED_TEXT) {
statusViewTop.setText("");
statusViewTop.setTextSize(14);
statusViewTop.setVisibility(View.VISIBLE);
}
viewfinderView.setVisibility(View.VISIBLE);
cameraButtonView.setVisibility(View.VISIBLE);
lastResult = null;
viewfinderView.removeResultText();
}
/** Displays a pop-up message showing the name of the current OCR source language. */
void showLanguageName() {
Toast toast = Toast.makeText(this, "OCR: " + sourceLanguageReadable, Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP, 0, 0);
toast.show();
}
/**
* Displays an initial message to the user while waiting for the first OCR request to be
* completed after starting realtime OCR.
*/
void setStatusViewForContinuous() {
viewfinderView.removeResultText();
if (CONTINUOUS_DISPLAY_METADATA) {
statusViewBottom.setText("OCR: " + sourceLanguageReadable + " - waiting for OCR...");
}
}
/** Request the viewfinder to be invalidated. */
void drawViewfinder() {
viewfinderView.drawViewfinder();
}
/**
* Requests autofocus after a 350 ms delay. This delay prevents requesting focus when the user
* just wants to click the shutter button without focusing. Quick button press/release will
* trigger onShutterButtonClick() before the focus kicks in.
*/
private void requestDelayedAutoFocus() {
// Wait 350 ms before focusing to avoid interfering with quick button presses when
// the user just wants to take a picture without focusing.
cameraManager.requestAutoFocus(350L);
}
static boolean getFirstLaunch() {
return isFirstLaunch;
}
/**
* We want the help screen to be shown automatically the first time a new version of the app is
* run. The easiest way to do this is to check android:versionCode from the manifest, and compare
* it to a value stored as a preference.
*/
private boolean checkFirstLaunch() {
try {
PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), 0);
int currentVersion = info.versionCode;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
int lastVersion = prefs.getInt(PreferencesActivity.KEY_HELP_VERSION_SHOWN, 0);
if (lastVersion == 0) {
isFirstLaunch = true;
} else {
isFirstLaunch = false;
}
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, e);
}
return false;
}
/**
* Returns a string that represents which OCR engine(s) are currently set to be run.
*
* @return OCR engine mode
*/
String getOcrEngineModeName() {
String ocrEngineModeName = "";
String[] ocrEngineModes = getResources().getStringArray(R.array.ocrenginemodes);
if (ocrEngineMode == TessBaseAPI.OEM_TESSERACT_ONLY) {
ocrEngineModeName = ocrEngineModes[0];
} else if (ocrEngineMode == TessBaseAPI.OEM_CUBE_ONLY) {
ocrEngineModeName = ocrEngineModes[1];
} else if (ocrEngineMode == TessBaseAPI.OEM_TESSERACT_CUBE_COMBINED) {
ocrEngineModeName = ocrEngineModes[2];
}
return ocrEngineModeName;
}
/**
* Gets values from shared preferences and sets the corresponding data members in this activity.
*/
private void retrievePreferences() {
prefs = PreferenceManager.getDefaultSharedPreferences(this);
// Retrieve from preferences, and set in this Activity, the language preferences
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
setSourceLanguage(prefs.getString(PreferencesActivity.KEY_SOURCE_LANGUAGE_PREFERENCE, CaptureActivity.DEFAULT_SOURCE_LANGUAGE_CODE));
setTargetLanguage(prefs.getString(PreferencesActivity.KEY_TARGET_LANGUAGE_PREFERENCE, CaptureActivity.DEFAULT_TARGET_LANGUAGE_CODE));
isTranslationActive = prefs.getBoolean(PreferencesActivity.KEY_TOGGLE_TRANSLATION, false);
// Retrieve from preferences, and set in this Activity, the capture mode preference
if (prefs.getBoolean(PreferencesActivity.KEY_CONTINUOUS_PREVIEW, CaptureActivity.DEFAULT_TOGGLE_CONTINUOUS)) {
isContinuousModeActive = true;
} else {
isContinuousModeActive = false;
}
// Retrieve from preferences, and set in this Activity, the page segmentation mode preference
String[] pageSegmentationModes = getResources().getStringArray(R.array.pagesegmentationmodes);
String pageSegmentationModeName = prefs.getString(PreferencesActivity.KEY_PAGE_SEGMENTATION_MODE, pageSegmentationModes[0]);
if (pageSegmentationModeName.equals(pageSegmentationModes[0])) {
pageSegmentationMode = TessBaseAPI.PSM_AUTO_OSD;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[1])) {
pageSegmentationMode = TessBaseAPI.PSM_AUTO;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[2])) {
pageSegmentationMode = TessBaseAPI.PSM_SINGLE_BLOCK;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[3])) {
pageSegmentationMode = TessBaseAPI.PSM_SINGLE_CHAR;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[4])) {
pageSegmentationMode = TessBaseAPI.PSM_SINGLE_COLUMN;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[5])) {
pageSegmentationMode = TessBaseAPI.PSM_SINGLE_LINE;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[6])) {
pageSegmentationMode = TessBaseAPI.PSM_SINGLE_WORD;
} else if (pageSegmentationModeName.equals(pageSegmentationModes[7])) {
pageSegmentationMode = TessBaseAPI.PSM_SINGLE_BLOCK_VERT_TEXT;
}
// Retrieve from preferences, and set in this Activity, the OCR engine mode
String[] ocrEngineModes = getResources().getStringArray(R.array.ocrenginemodes);
String ocrEngineModeName = prefs.getString(PreferencesActivity.KEY_OCR_ENGINE_MODE, ocrEngineModes[0]);
if (ocrEngineModeName.equals(ocrEngineModes[0])) {
ocrEngineMode = TessBaseAPI.OEM_TESSERACT_ONLY;
} else if (ocrEngineModeName.equals(ocrEngineModes[1])) {
ocrEngineMode = TessBaseAPI.OEM_CUBE_ONLY;
} else if (ocrEngineModeName.equals(ocrEngineModes[2])) {
ocrEngineMode = TessBaseAPI.OEM_TESSERACT_CUBE_COMBINED;
}
// Retrieve from preferences, and set in this Activity, the character blacklist and whitelist
characterBlacklist = "qazxswedcvfrtgbnhyujmkiol,.�p>";//OcrCharacterHelper.getBlacklist(prefs, sourceLanguageCodeOcr);
characterWhitelist = "QWERTYUIOP�LKJHGFDSAZXCVBNM1234567890<";//OcrCharacterHelper.getWhitelist(prefs, sourceLanguageCodeOcr);
prefs.registerOnSharedPreferenceChangeListener(listener);
beepManager.updatePrefs();
}
/**
* Sets default values for preferences. To be called the first time this app is run.
*/
private void setDefaultPreferences() {
prefs = PreferenceManager.getDefaultSharedPreferences(this);
// Continuous preview
prefs.edit().putBoolean(PreferencesActivity.KEY_CONTINUOUS_PREVIEW, CaptureActivity.DEFAULT_TOGGLE_CONTINUOUS).commit();
// Recognition language
prefs.edit().putString(PreferencesActivity.KEY_SOURCE_LANGUAGE_PREFERENCE, CaptureActivity.DEFAULT_SOURCE_LANGUAGE_CODE).commit();
// Translation
prefs.edit().putBoolean(PreferencesActivity.KEY_TOGGLE_TRANSLATION, CaptureActivity.DEFAULT_TOGGLE_TRANSLATION).commit();
// Translation target language
prefs.edit().putString(PreferencesActivity.KEY_TARGET_LANGUAGE_PREFERENCE, CaptureActivity.DEFAULT_TARGET_LANGUAGE_CODE).commit();
// Translator
prefs.edit().putString(PreferencesActivity.KEY_TRANSLATOR, CaptureActivity.DEFAULT_TRANSLATOR).commit();
// OCR Engine
prefs.edit().putString(PreferencesActivity.KEY_OCR_ENGINE_MODE, CaptureActivity.DEFAULT_OCR_ENGINE_MODE).commit();
// Autofocus
prefs.edit().putBoolean(PreferencesActivity.KEY_AUTO_FOCUS, CaptureActivity.DEFAULT_TOGGLE_AUTO_FOCUS).commit();
// Beep
prefs.edit().putBoolean(PreferencesActivity.KEY_PLAY_BEEP, CaptureActivity.DEFAULT_TOGGLE_BEEP).commit();
// Character blacklist
prefs.edit().putString(PreferencesActivity.KEY_CHARACTER_BLACKLIST,
OcrCharacterHelper.getDefaultBlacklist(CaptureActivity.DEFAULT_SOURCE_LANGUAGE_CODE)).commit();
// Character whitelist
prefs.edit().putString(PreferencesActivity.KEY_CHARACTER_WHITELIST,
OcrCharacterHelper.getDefaultWhitelist(CaptureActivity.DEFAULT_SOURCE_LANGUAGE_CODE)).commit();
// Page segmentation mode
prefs.edit().putString(PreferencesActivity.KEY_PAGE_SEGMENTATION_MODE, CaptureActivity.DEFAULT_PAGE_SEGMENTATION_MODE).commit();
// Reversed camera image
prefs.edit().putBoolean(PreferencesActivity.KEY_REVERSE_IMAGE, CaptureActivity.DEFAULT_TOGGLE_REVERSED_IMAGE).commit();
// Light
prefs.edit().putBoolean(PreferencesActivity.KEY_TOGGLE_LIGHT, CaptureActivity.DEFAULT_TOGGLE_LIGHT).commit();
}
void displayProgressDialog() {
// Set up the indeterminate progress dialog box
indeterminateDialog = new ProgressDialog(this);
indeterminateDialog.setTitle("Please wait");
String ocrEngineModeName = getOcrEngineModeName();
if (ocrEngineModeName.equals("Both")) {
indeterminateDialog.setMessage("Performing OCR...");
} else {
indeterminateDialog.setMessage("Performing OCR...");
}
indeterminateDialog.setCancelable(false);
indeterminateDialog.show();
}
ProgressDialog getProgressDialog() {
return indeterminateDialog;
}
/**
* Displays an error message dialog box to the user on the UI thread.
*
* @param title The title for the dialog box
* @param message The error message to be displayed
*/
void showErrorMessage(String title, String message) {
new AlertDialog.Builder(this)
.setTitle(title)
.setMessage(message)
.setOnCancelListener(new FinishListener(this))
.setPositiveButton( "Done", new FinishListener(this))
.show();
}
}