title: Easy OCR Library Does Not Work
body: <p>This is my first Android App project and I am trying to apply OCR function in my Android App by using Easy OCR library made by <a href="https://priyankvex.wordpress.com/2015/09/02/making-an-ocr-app-for-android-using-tesseract/" rel="nofollow noreferrer">Priyank Verma</a>'s <a href="https://github.com/priyankvex/Easy-Ocr-Scanner-Android" rel="nofollow noreferrer">Easy OCR Library</a> as it is the most simplified &amp; most recent OCR library I can get on. But I think the creator of that library wont answer people's query in his own blog, so I try to ask here. If this is not a good question, I will delete it.</p>
  
  <p>So here's the problem, I have an app with four tabs and in one of the tabs, I tried to use the library example which I try to apply them in my tab. In that tab, there's a 'Scan' button that will take a picture, save it and then scan it. After that, it should return output of text characters from the scanning process. And the execution of the app successfully return with zero error.</p>
  
  <p>But the problem here is, it failed to save the picture by which it will lead the failure of the scanning process thus returning nothing. I can't see any problem here, maybe someone with sharp eyes can detect them?</p>
  
  <h2><strong>||||| UPDATE 1 |||||</strong></h2>
  
  <p>I have set breakpoints as suggested by <a href="https://stackoverflow.com/questions/37935423/easy-ocr-library-does-not-work?noredirect=1#comment63334347_37935423">Ishita Sinha</a> and I have found out the file did save, it just saved on different directory which is on my internal storage (<em>/storage/emulated/0/EasyOcrScanner</em> or <em>internal storage/EasyOcrScanner</em>). The real conflict occur here is when after the image have been saved, which is scanning of the image. Still, I can't figure out why is that. I have marked '<strong><em>%%</em></strong>' in the <strong><em>FileUtils Java</em></strong> and <strong><em>EasyOCRScanner Java</em></strong> to show what I have found. I need some assist on how to successfully scan after the image has been saved.</p>
  
  <h2><strong>||||||||||||||||||||||||||||||</strong></h2>
  
  <h2><strong>||||| UPDATE 2 |||||</strong></h2>
  
  <p>I have pushed my project on GitHub as requested by <a href="https://stackoverflow.com/questions/37935423/easy-ocr-library-does-not-work?noredirect=1#comment63394322_37935423">Anand Savjani</a>. You guys can check there. The project name is 'Queue-App'.</p>
  
  <p><a href="https://github.com/Kaydarin/Queue-App" rel="nofollow noreferrer">https://github.com/Kaydarin/Queue-App</a></p>
  
  <h2><strong>||||||||||||||||||||||||||||||</strong></h2>
  
  <p><strong>---------- From My App's Tab ----------</strong></p>
  
  <p><strong>My App's Manifest</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.kaydarinapp.queueappv2"&gt;
      &lt;!-- Save file permission --&gt;
      &lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/&gt;
      &lt;!-- Read file permission --&gt;
      &lt;uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /&gt;
      &lt;!-- Camera permission --&gt;
      &lt;uses-feature android:name="android.hardware.camera" /&gt;
      &lt;uses-permission android:name="android.permission.CAMERA" /&gt;
      &lt;!-- Internet permission --&gt;
      &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
      &lt;application
          android:allowBackup="true"
          android:icon="@mipmap/ic_launcher"
          android:label="@string/app_name"
          android:supportsRtl="true"
          android:theme="@style/AppTheme"&gt;
          &lt;activity android:name=".MainActivity"
              android:screenOrientation="portrait"
              android:configChanges="keyboardHidden|orientation|screenSize"&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="android.intent.action.MAIN" /&gt;
  
                  &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
              &lt;/intent-filter&gt;
          &lt;/activity&gt;
      &lt;/application&gt;
  
  &lt;/manifest&gt;
  </code></pre>
  
  <p><strong>My Tab's XML</strong></p>
  
  <pre><code>&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
      android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
      android:paddingRight="@dimen/activity_horizontal_margin"
      android:paddingTop="@dimen/activity_vertical_margin"
      android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".Tab2"
      android:gravity="center_horizontal"
      &gt;
  
      &lt;TextView android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:id="@+id/textView"
          android:layout_marginTop="45dp"
          android:layout_gravity="center_horizontal"
          android:textSize="8pt"
          /&gt;
  
  
      &lt;Button
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:id="@+id/button"
          android:layout_marginTop="20dp"
          android:text="Scan"
          android:layout_gravity="center_vertical" /&gt;
  
  &lt;/LinearLayout&gt;
  </code></pre>
  
  <p><strong>My Tab Java</strong></p>
  
  <pre><code>package com.kaydarinapp.queueappv2;
  import android.app.ProgressDialog;
  import android.content.Intent;
  import android.graphics.Bitmap;
  import android.os.Bundle;
  import android.support.v4.app.Fragment;
  import android.support.v4.app.FragmentActivity;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.Button;
  import android.widget.LinearLayout;
  import android.widget.TextView;
  
  import com.wordpress.priyankvex.easyocrscannerdemo.Config;
  import com.wordpress.priyankvex.easyocrscannerdemo.EasyOcrScanner;
  import com.wordpress.priyankvex.easyocrscannerdemo.EasyOcrScannerListener;
  
  /**
   * Created by Kaydarin on 6/1/2016.
   */
  
  //Our class extending fragment
  public class Tab2 extends Fragment implements EasyOcrScannerListener {
  
      private LinearLayout linearLayout;
      private FragmentActivity fragActivity;
      EasyOcrScanner mEasyOcrScanner;
      TextView textView;
      ProgressDialog mProgressDialog;
      Button btnCapture;
  
      //Overriden method onCreateView
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
          fragActivity = super.getActivity();
          linearLayout = (LinearLayout) inflater.inflate(R.layout.tab2, container, false);
  
          textView = (TextView) fragActivity.findViewById(R.id.textView);
  
          // initialize EasyOcrScanner instance.
          mEasyOcrScanner = new EasyOcrScanner(getActivity(), "EasyOcrScanner",
                  Config.REQUEST_CODE_CAPTURE_IMAGE, "eng");
  
          // Set ocrScannerListener
          mEasyOcrScanner.setOcrScannerListener(this);
  
          btnCapture = (Button) linearLayout.findViewById(R.id.button);
          btnCapture.setOnClickListener(new View.OnClickListener(){
              @Override
              public void onClick(View v) {
                  mEasyOcrScanner.takePicture();
              }
          });
  
          return linearLayout;
      }
  
      @Override
      public void onActivityResult(int requestCode, int resultCode, Intent data) {
          super.onActivityResult(requestCode, resultCode, data);
          // Call onImageTaken() in onActivityResult.
          if (resultCode == getActivity().RESULT_OK &amp;&amp; requestCode == Config.REQUEST_CODE_CAPTURE_IMAGE){
              mEasyOcrScanner.onImageTaken();
          }
      }
  
      /**
       * Callback when after taking picture, scanning process starts.
       * Good place to show a progress dialog.
       * @param filePath file path of the image file being processed.
       */
      @Override
      public void onOcrScanStarted(String filePath) {
          mProgressDialog = new ProgressDialog(getActivity());
          mProgressDialog.setMessage("Scanning...");
          mProgressDialog.show();
      }
  
      /**
       * Callback when scanning is finished.
       * Good place to hide teh progress dialog.
       * @param bitmap Bitmap of image that was scanned.
       * @param recognizedText Scanned text.
       */
      @Override
      public void onOcrScanFinished(Bitmap bitmap, String recognizedText) {
          textView.setText(recognizedText);
          if (mProgressDialog.isShowing()){
              mProgressDialog.dismiss();
          }
      }
  }
  </code></pre>
  
  <p><strong>---------- From Easy OCR Library ----------</strong></p>
  
  <p><strong>Easy OCR Library's Manifest</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.wordpress.priyankvex.easyocrscanner"&gt;
  
      &lt;uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /&gt;
      &lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&gt;
      &lt;uses-permission android:name="android.permission.CAMERA"/&gt;
  
  &lt;/manifest&gt;
  </code></pre>
  
  <p><strong>Config Java</strong></p>
  
  <pre><code>package com.wordpress.priyankvex.easyocrscannerdemo;
  
  /**
   * Created by Priyank(@priyankvex) on 27/8/15.
   */
  public class Config {
  
      public static String TAG = "OcrScanner";
      public static int REQUEST_CODE_CAPTURE_IMAGE = 1995;
  
  }
  </code></pre>
  
  <p><strong>EasyOCRScannerListener Java</strong></p>
  
  <pre><code>package com.wordpress.priyankvex.easyocrscannerdemo;
  
  import android.graphics.Bitmap;
  
  /**
   * Created by Priyank(@priyankvex) on 27/8/15.
   *
   * Interface for the callbacks for {@link EasyOcrScanner}.
   */
  public interface EasyOcrScannerListener {
  
      public void onOcrScanStarted(String filePath);
  
      public void onOcrScanFinished(Bitmap bitmap, String recognizedText);
  }
  </code></pre>
  
  <p><strong>EasyOCRScanner Java</strong></p>
  
  <pre><code>package com.wordpress.priyankvex.easyocrscannerdemo;
  
  import android.app.Activity;
  import android.content.Intent;
  import android.net.Uri;
  import android.util.Log;
  
  import java.io.File;
  import java.util.Calendar;
  
  /**
   * Created by Priyank(@priyankvex) on 27/8/15.
   *
   * Class to handle scanning of image.
   */
  public class EasyOcrScanner {
  
      protected Activity mActivity;
      private String directoryPathOriginal;
      private String filePathOriginal;
      private int requestCode;
      private EasyOcrScannerListener mOcrScannerListener;
      private String trainedDataCode;
  
      public EasyOcrScanner(Activity activity, String directoryPath, int requestCode, String trainedDataCode){
          this.mActivity = activity;
          this.directoryPathOriginal = directoryPath;
          this.requestCode = requestCode;
          this.trainedDataCode = trainedDataCode;
      }
  
      public void takePicture(){
          Intent e = new Intent("android.media.action.IMAGE_CAPTURE");
          this.filePathOriginal = FileUtils.getDirectory(this.directoryPathOriginal) + File.separator + Calendar.getInstance().getTimeInMillis() + ".jpg";
          e.putExtra("output", Uri.fromFile(new File(this.filePathOriginal)));
  
          startActivity(e);
      } // %%%%%%%%%%%% POSITIVE BREAKPOINT: AFTER THIS POINT, THE APP DOES NOT APPEAR TO SCAN THE CAPTURED IMAGE AS IT RETURN BACK TO THE APP WITHOUT ANY SCANNED TEXT OUTPUT %%%%%%%%%%%%
  
      public void onImageTaken(){
          Log.d(Config.TAG, "onImageTaken with path " + this.filePathOriginal);
          ImageProcessingThread thread = new ImageProcessingThread(this.mOcrScannerListener,
                  this.filePathOriginal, this.directoryPathOriginal, this.mActivity, this.trainedDataCode);
          thread.execute();
      }
  
      private void startActivity(Intent intent){
          if(this.mActivity != null) {
              this.mActivity.startActivityForResult(intent, this.requestCode);
          }
      }
  
      public void setOcrScannerListener(EasyOcrScannerListener mOcrScannerListener) {
          this.mOcrScannerListener = mOcrScannerListener;
      }
  
  
  }
  </code></pre>
  
  <p><strong>FileUtils Java</strong></p>
  
  <pre><code>package com.wordpress.priyankvex.easyocrscannerdemo;
  
  import android.os.Environment;
  import android.util.Log;
  
  import java.io.File;
  
  /**
   * Created by Priyank(@priyankvex) on 27/8/15.
   */
  public class FileUtils {
  
      public static String getDirectory(String folderName) {
          File directory = null;
          directory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + folderName);
          if(!directory.exists()) {
              directory.mkdirs();
          }
  
          return directory.getAbsolutePath(); // %%%%%%%%%%%% POSITIVE BREAKPOINT: IT SHOWS THAT THE FILE DIRECTORY SAVED IN INTERNAL STORAGE %%%%%%%%%%%%
      }
  
      public static String getTessdataDirectory(String directoryPath){
          File tessdataDirectory = new File(directoryPath + "/tessdata");
          if (tessdataDirectory.mkdirs()){
              Log.d(Config.TAG, "tessdata directory created");
          }
          return tessdataDirectory.getAbsolutePath();
      }
  }
  </code></pre>
  
  <p><strong>ImageProcessingThread Java</strong></p>
  
  <pre><code>package com.wordpress.priyankvex.easyocrscannerdemo;
  
  import android.app.Activity;
  import android.content.res.AssetManager;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.graphics.Matrix;
  import android.media.ExifInterface;
  import android.os.AsyncTask;
  import android.util.Log;
  
  import com.googlecode.tesseract.android.TessBaseAPI;
  
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  
  /**
   * Created by Priyank(@priyankvex) on 27/8/15.
   *
   * Async Task to process the image and scan the image using tesseract library.
   * Equipped with proper callbacks.
   */
  public class ImageProcessingThread extends AsyncTask&lt;Void, Void, Void&gt; {
  
      private EasyOcrScannerListener mOcrScannerListener;
      private String filePath;
      private Bitmap mBitmap;
      private String scannedText;
      // trained data file used by Tesseract will be copied in directoryPath/tessdata
      private String directoryPath;
      private String absoluteDirectoryPath;
      private Activity mActivity;
      String trainedDataCode;
  
      public ImageProcessingThread(EasyOcrScannerListener ocrScannerListener, String filePath,
                                   String directoryPath, Activity activity, String trainedDataCode) {
          this.mOcrScannerListener = ocrScannerListener;
          this.filePath = filePath;
          this.directoryPath = directoryPath;
          this.absoluteDirectoryPath = FileUtils.getDirectory(this.directoryPath);
          this.mActivity = activity;
          this.trainedDataCode = trainedDataCode;
      }
  
      @Override
      protected void onPreExecute() {
          super.onPreExecute();
          mOcrScannerListener.onOcrScanStarted(this.filePath);
      }
  
      @Override
      protected Void doInBackground(Void... params) {
          processImage();
          makeTessdataReady();
          scannedText = scanImage();
          Log.d(Config.TAG, "Scanned test : " + scannedText);
          return null;
      }
  
      @Override
      protected void onPostExecute(Void aVoid) {
          super.onPostExecute(aVoid);
          mOcrScannerListener.onOcrScanFinished(mBitmap, scannedText);
      }
  
      private void processImage() {
          int imageOrientationCode = getImageOrientation();
          Bitmap rawBitmap = getBitmapFromPath();
          // Getting the bitmap in right orientation.
          this.mBitmap = rotateBitmap(rawBitmap, imageOrientationCode);
      }
  
      private Bitmap getBitmapFromPath() {
          BitmapFactory.Options bmOptions = new BitmapFactory.Options();
          bmOptions.inSampleSize = 4;
          Bitmap bitmap = BitmapFactory.decodeFile(this.filePath, bmOptions);
          return bitmap;
      }
  
      private int getImageOrientation() {
          ExifInterface exif = null;
          try {
              exif = new ExifInterface(this.filePath);
          } catch (IOException e) {
              e.printStackTrace();
          }
  
          assert exif != null;
          int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                  ExifInterface.ORIENTATION_UNDEFINED);
          return orientation;
      }
  
      private Bitmap rotateBitmap(Bitmap bitmap, int orientation){
  
          Matrix matrix = new Matrix();
          switch (orientation) {
              case ExifInterface.ORIENTATION_NORMAL:
                  return bitmap;
              case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                  matrix.setScale(-1, 1);
                  break;
              case ExifInterface.ORIENTATION_ROTATE_180:
                  matrix.setRotate(180);
                  break;
              case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                  matrix.setRotate(180);
                  matrix.postScale(-1, 1);
                  break;
              case ExifInterface.ORIENTATION_TRANSPOSE:
                  matrix.setRotate(90);
                  matrix.postScale(-1, 1);
                  break;
              case ExifInterface.ORIENTATION_ROTATE_90:
                  matrix.setRotate(90);
                  break;
              case ExifInterface.ORIENTATION_TRANSVERSE:
                  matrix.setRotate(-90);
                  matrix.postScale(-1, 1);
                  break;
              case ExifInterface.ORIENTATION_ROTATE_270:
                  matrix.setRotate(-90);
                  break;
              default:
                  return bitmap;
          }
          try {
              Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
              bitmap.recycle();
              return bmRotated;
          }
          catch (OutOfMemoryError e) {
              e.printStackTrace();
              return null;
          }
      }
  
      private String scanImage(){
          TessBaseAPI baseApi = new TessBaseAPI();
          Log.d(Config.TAG, "Data path : " + FileUtils.getDirectory(this.directoryPath));
          baseApi.init(FileUtils.getDirectory(this.directoryPath) + "/", this.trainedDataCode);
          baseApi.setImage(this.mBitmap);
          String recognizedText = baseApi.getUTF8Text();
          baseApi.end();
  
          return recognizedText;
      }
  
      private void makeTessdataReady(){
  
          // created tessdata directory if necessary under absoluteDirectoryPath and returns its absolute path.
          String tessdirectoryPath = FileUtils.getTessdataDirectory(this.absoluteDirectoryPath);
  
          if (!(new File(tessdirectoryPath+ "/" + this.trainedDataCode + ".traineddata")).exists()) {
              try {
  
                  AssetManager assetManager = mActivity.getAssets();
                  InputStream in = assetManager.open("tessdata/" + this.trainedDataCode + ".traineddata");
                  //GZIPInputStream gin = new GZIPInputStream(in);
                  // Output stream with the location where we have to write the eng.traineddata file.
                  OutputStream out = new FileOutputStream(tessdirectoryPath + "/"  + this.trainedDataCode
                          + ".traineddata");
  
                  // Transfer bytes from in to out
                  byte[] buf = new byte[1024];
                  int len;
                  //while ((lenf = gin.read(buff)) &gt; 0) {
                  while ((len = in.read(buf)) &gt; 0) {
                      out.write(buf, 0, len);
                  }
                  in.close();
                  //gin.close();
                  out.close();
  
                  Log.v(Config.TAG, "Copied " + " traineddata");
              } catch (IOException e) {
                  Log.e(Config.TAG, "Was unable to copy " + " traineddata " + e.toString());
              }
          }
          else{
              Log.d(Config.TAG, "tessdata already present");
          }
      }
  
  }
  </code></pre>
  
  <p>Hope someone can me help here. Really appreciate it.....</p>