/* * 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(); } }