<commit_before>package com.juleskelly.tesseract;

// android imports
import android.os.Bundle;
import android.os.Environment;
import android.content.res.AssetManager;
import android.util.Log;
import android.util.Base64;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;


// java imports
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.*;

// cordova imports
import org.apache.cordova.*;
import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;

// TessBaseAPI import for tesseract
import com.googlecode.tesseract.android.TessBaseAPI;

public class TesseractOCR extends CordovaPlugin {
  public final String ACTION_LOADENGINE = "loadEngine";
  public final String ACTION_RECOGNIZEIMAGE = "recognizeImage";
  public final String DATA_PATH = Environment.getExternalStorageDirectory().toString() + "/OCRFolder/";
  public final String TAG = "OCREngine";
  public final String lang = "eng";

  @Override
  public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
    if (ACTION_LOADENGINE.equals(action)) {
      loadEngine(callbackContext);
      return true;
    }
    else if (ACTION_RECOGNIZEIMAGE.equals(action)) {
      JSONObject arg_obj = args.getJSONObject(0);
      String imagePath = arg_obj.getString("imageURL");

      recognizeImage(imagePath, callbackContext);
    };


    return false;
  }

  // load training data for tesseract
  public void loadEngine(final CallbackContext callbackContext) {
    String[] paths = new String[] {DATA_PATH, DATA_PATH + "tessdata/"};
    // create directories if they did not exist
    for (String path : paths) {
      File dir = new File(path);

      if (!dir.exists()) {
        if (!dir.mkdirs()) {
          Log.e(TAG, "Error: Creation of directory " + path + " on sdcard failed");
          callbackContext.error("Error: Creation of directory " + path + " on sdcard failed");
          return;
        }
        else {
          Log.e(TAG, "Directory " + path + " created on sdcard.");
        }
      }
      else {
        Log.e(TAG, "Directory already exists");
      }
    }

    // copy trained data if file doesn't exist
    if (!(new File(DATA_PATH + "tessdata/" + lang + ".traineddata")).exists()) {
      try {
        AssetManager assetManager = cordova.getActivity().getApplicationContext().getAssets();
        InputStream in = assetManager.open("tessdata/" + lang + ".traineddata");
        OutputStream out = new FileOutputStream(DATA_PATH + "tessdata/" + lang + ".traineddata");

        byte[] buf = new byte[1024]; // 1024 bytes = 1 KB
        int len;

        while ((len = in.read(buf)) > 0) {
          out.write(buf, 0, len);
        }
        in.close();
        out.close();

        Log.e(TAG, "Copied " + lang + ".traineddata successfully");
      }
      catch (IOException e) {
        Log.e(TAG, "Unable to copy " + lang + ".traineddata: " + e.toString());
        callbackContext.error("Unable to copy " + lang + ".traineddata: " + e.toString());
        return;
      }
    }
    else
      Log.e(TAG, "Train data file already exists");

    Log.e(TAG, "Tesseract engine has been loaded");
    callbackContext.success("Tesseract engine has been loaded");
  }

  // recognize the image using tesseract
  public void recognizeImage(String imageURL, final CallbackContext callbackContext) {
    BitmapFactory.Options options = new BitmapFactory.Options();

    Log.e(TAG, imageURL);
    byte[] decodedBytes = Base64.decode(imageURL, Base64.DEFAULT);
    Log.e(TAG, "Starting image decoding...");

      Bitmap bitmap = BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length, options);
      bitmap = Bitmap.createScaledBitmap(bitmap, 3120, 4160, false);
      int imageHeight = options.outHeight;
      int imageWidth = options.outWidth;
      Log.e(TAG, "Dimension de la imagen width "+ imageWidth+ ", height "+ imageHeight);

          try {

      bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);

      // scan and recognize the bitmap image
      String recognizedText = "";
      String recognizedBlocks = "";

      Log.e(TAG, "Before baseApi");
      TessBaseAPI baseApi = new TessBaseAPI();
      baseApi.setDebug(true);
      baseApi.setPageSegMode(1);
      baseApi.init(DATA_PATH, lang);
      baseApi.setVariable("tessedit_char_whitelist", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ(),.-+auroilnsrmtv");
      baseApi.setImage(bitmap);
      recognizedText = baseApi.getUTF8Text();
      //Log.e(TAG,"OCR wordConfidences" + Arrays.toString(baseApi.wordConfidences().getGeometry()));
      Log.e(TAG,"OCR meanConfidence" + baseApi.meanConfidence());
      Log.e(TAG, "OCRED Text: " + recognizedText);

      /*
      int total_width = baseApi.getRegions().getBox(0).getWidth();
      int blocks_y = baseApi.getTextlines().getBox(2).getY();
      int blocks_height = 0;<commit_msg>binary image<commit_after>package com.juleskelly.tesseract;

// android imports
import android.os.Bundle;
import android.os.Environment;
import android.content.res.AssetManager;
import android.util.Log;
import android.util.Base64;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;


// java imports
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.*;

// cordova imports
import org.apache.cordova.*;
import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;

// TessBaseAPI import for tesseract
import com.googlecode.tesseract.android.TessBaseAPI;

public class TesseractOCR extends CordovaPlugin {
  public final String ACTION_LOADENGINE = "loadEngine";
  public final String ACTION_RECOGNIZEIMAGE = "recognizeImage";
  public final String DATA_PATH = Environment.getExternalStorageDirectory().toString() + "/OCRFolder/";
  public final String TAG = "OCREngine";
  public final String lang = "eng";

  @Override
  public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
    if (ACTION_LOADENGINE.equals(action)) {
      loadEngine(callbackContext);
      return true;
    }
    else if (ACTION_RECOGNIZEIMAGE.equals(action)) {
      JSONObject arg_obj = args.getJSONObject(0);
      String imagePath = arg_obj.getString("imageURL");

      recognizeImage(imagePath, callbackContext);
    };


    return false;
  }

  // load training data for tesseract
  public void loadEngine(final CallbackContext callbackContext) {
    String[] paths = new String[] {DATA_PATH, DATA_PATH + "tessdata/"};
    // create directories if they did not exist
    for (String path : paths) {
      File dir = new File(path);

      if (!dir.exists()) {
        if (!dir.mkdirs()) {
          Log.e(TAG, "Error: Creation of directory " + path + " on sdcard failed");
          callbackContext.error("Error: Creation of directory " + path + " on sdcard failed");
          return;
        }
        else {
          Log.e(TAG, "Directory " + path + " created on sdcard.");
        }
      }
      else {
        Log.e(TAG, "Directory already exists");
      }
    }

    // copy trained data if file doesn't exist
    if (!(new File(DATA_PATH + "tessdata/" + lang + ".traineddata")).exists()) {
      try {
        AssetManager assetManager = cordova.getActivity().getApplicationContext().getAssets();
        InputStream in = assetManager.open("tessdata/" + lang + ".traineddata");
        OutputStream out = new FileOutputStream(DATA_PATH + "tessdata/" + lang + ".traineddata");

        byte[] buf = new byte[1024]; // 1024 bytes = 1 KB
        int len;

        while ((len = in.read(buf)) > 0) {
          out.write(buf, 0, len);
        }
        in.close();
        out.close();

        Log.e(TAG, "Copied " + lang + ".traineddata successfully");
      }
      catch (IOException e) {
        Log.e(TAG, "Unable to copy " + lang + ".traineddata: " + e.toString());
        callbackContext.error("Unable to copy " + lang + ".traineddata: " + e.toString());
        return;
      }
    }
    else
      Log.e(TAG, "Train data file already exists");

    Log.e(TAG, "Tesseract engine has been loaded");
    callbackContext.success("Tesseract engine has been loaded");
  }


  public static Bitmap createBinaryImage( Bitmap bm ){
    int[] pixels = new int[bm.getWidth()*bm.getHeight()];
    bm.getPixels( pixels, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight() );
    int w = bm.getWidth();

    // Calculate overall lightness of image
    long gLightness = 0;
    int lLightness;
    int c;
    for ( int x = 0; x < bm.getWidth(); x++ )
    {
        for ( int y = 0; y < bm.getHeight(); y++ )
        {
            c = pixels[x+y*w];
            lLightness = ((c&0x00FF0000 )>>16) + ((c & 0x0000FF00 )>>8) + (c&0x000000FF);
            pixels[x+y*w] = lLightness;
            gLightness += lLightness;
        }
    }
    gLightness /= bm.getWidth() * bm.getHeight();
    gLightness = gLightness * 5 / 6;

    Bitmap bitmap = bm.copy(Bitmap.Config.ARGB_8888, true);

    for ( int x = 0; x < bm.getWidth(); x++ )
        for ( int y = 0; y < bm.getHeight(); y++ )
            binaryImage[x][y] = pixels[x+y*w] <= gLightness;
          if (pixels[x+y*w] <= gLightness){
            bitmap.setPixel(x,y, Color.BLACK)
          }else{
            bitmap.setPixel(x,y, Color.WHITE)
          }

    return bitmap;
  }

  // recognize the image using tesseract
  public void recognizeImage(String imageURL, final CallbackContext callbackContext) {
    BitmapFactory.Options options = new BitmapFactory.Options();

    Log.e(TAG, imageURL);
    byte[] decodedBytes = Base64.decode(imageURL, Base64.DEFAULT);
    Log.e(TAG, "Starting image decoding...");

      Bitmap bitmap = BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length, options);
      int imageHeight = options.outHeight;
      int imageWidth = options.outWidth;
      Log.e(TAG, "Dimension de la imagen width "+ imageWidth+ ", height "+ imageHeight);

      try {

        bitmap = createBinaryImage(bitmap);

      // scan and recognize the bitmap image
      String recognizedText = "";

      Log.e(TAG, "Before baseApi");
      TessBaseAPI baseApi = new TessBaseAPI();
      baseApi.setDebug(true);
      baseApi.setPageSegMode(1);
      baseApi.init(DATA_PATH, lang);
      baseApi.setVariable("tessedit_char_whitelist", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ(),.-+auroilnsrmtv");
      baseApi.setImage(bitmap);
      recognizedText = baseApi.getUTF8Text();
      //Log.e(TAG,"OCR wordConfidences" + Arrays.toString(baseApi.wordConfidences().getGeometry()));
      Log.e(TAG,"OCR meanConfidence" + baseApi.meanConfidence());
      Log.e(TAG, "OCRED Text: " + recognizedText);

      /*
      int total_width = baseApi.getRegions().getBox(0).getWidth();
      int blocks_y = baseApi.getTextlines().getBox(2).getY();
      int blocks_height = 0;
{'fraction_non_alphanumeric': 0.12673375033995105, 'fraction_numerical': 0.010697126280482278, 'mean_word_length': 3.030690537084399, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2987668', 'n_tokens_mistral': 3461, 'n_tokens_neox': 3302, 'n_words': 818}