react-native-text-reader 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -63,7 +63,6 @@ android {
63
63
  defaultConfig {
64
64
  minSdkVersion getExtOrIntegerDefault("minSdkVersion")
65
65
  targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
66
-
67
66
  }
68
67
 
69
68
  buildTypes {
@@ -74,6 +73,7 @@ android {
74
73
 
75
74
  lintOptions {
76
75
  disable "GradleCompatible"
76
+ abortOnError false
77
77
  }
78
78
 
79
79
  compileOptions {
@@ -95,5 +95,16 @@ dependencies {
95
95
  //noinspection GradleDynamicVersion
96
96
  implementation "com.facebook.react:react-native:+"
97
97
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
98
+
99
+ // To recognize Latin script
100
+ implementation 'com.google.mlkit:text-recognition:16.0.1'
101
+ // To recognize Chinese script
102
+ implementation 'com.google.mlkit:text-recognition-chinese:16.0.1'
103
+ // To recognize Devanagari script
104
+ implementation 'com.google.mlkit:text-recognition-devanagari:16.0.1'
105
+ // To recognize Japanese script
106
+ implementation 'com.google.mlkit:text-recognition-japanese:16.0.1'
107
+ // To recognize Korean script
108
+ implementation 'com.google.mlkit:text-recognition-korean:16.0.1'
98
109
  }
99
110
 
@@ -5,21 +5,149 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule
5
5
  import com.facebook.react.bridge.ReactMethod
6
6
  import com.facebook.react.bridge.Promise
7
7
 
8
+ import android.graphics.Point
9
+ import android.graphics.Rect
10
+ import android.net.Uri
11
+ import android.graphics.BitmapFactory
12
+ import android.graphics.Bitmap
13
+ import androidx.annotation.NonNull
14
+ import androidx.annotation.Nullable
15
+ import com.facebook.react.bridge.*
16
+ import com.google.android.gms.tasks.OnFailureListener
17
+ import com.google.android.gms.tasks.OnSuccessListener
18
+ import com.google.mlkit.vision.common.InputImage
19
+ import com.google.mlkit.vision.text.Text
20
+ import com.google.mlkit.vision.text.TextRecognition
21
+ import com.google.mlkit.vision.text.TextRecognizer
22
+ import com.google.mlkit.vision.text.TextRecognizerOptionsInterface
23
+ import com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions
24
+ import com.google.mlkit.vision.text.devanagari.DevanagariTextRecognizerOptions
25
+ import com.google.mlkit.vision.text.japanese.JapaneseTextRecognizerOptions
26
+ import com.google.mlkit.vision.text.korean.KoreanTextRecognizerOptions
27
+ import com.google.mlkit.vision.text.latin.TextRecognizerOptions
28
+ import java.io.IOException
29
+ import java.net.URL
30
+
8
31
  class TextReaderModule(reactContext: ReactApplicationContext) :
9
32
  ReactContextBaseJavaModule(reactContext) {
33
+ override fun getName(): String {
34
+ return "TextReader"
35
+ }
36
+
37
+ @Throws(IOException::class)
38
+ private fun getInputImage(reactContext: ReactApplicationContext, url: String): InputImage {
39
+ return if (url.contains("http://") || url.contains("https://")) {
40
+ val urlInput = URL(url)
41
+ val image: Bitmap = BitmapFactory.decodeStream(urlInput.openConnection().getInputStream())
42
+ InputImage.fromBitmap(image, 0)
43
+ } else {
44
+ val uri = Uri.parse(url)
45
+ InputImage.fromFilePath(reactContext, uri)
46
+ }
47
+ }
48
+
49
+ private fun rectToMap(rect: Rect): WritableMap {
50
+ return Arguments.createMap().apply {
51
+ putInt("width", rect.width())
52
+ putInt("height", rect.height())
53
+ putInt("top", rect.top)
54
+ putInt("left", rect.left)
55
+ }
56
+ }
57
+
58
+ private fun cornerPointsToMap(points: Array<Point>): WritableArray {
59
+ return Arguments.createArray().apply {
60
+ points.forEach { point ->
61
+ pushMap(Arguments.createMap().apply {
62
+ putInt("x", point.x)
63
+ putInt("y", point.y)
64
+ })
65
+ }
66
+ }
67
+ }
68
+
69
+ private fun langToMap(lang: String): WritableArray {
70
+ return Arguments.createArray().apply {
71
+ pushMap(Arguments.createMap().apply {
72
+ putString("languageCode", lang)
73
+ })
74
+ }
75
+ }
76
+
77
+ private fun lineToMap(line: Text.Line): WritableMap {
78
+ return Arguments.createMap().apply {
79
+ putString("text", line.text)
80
+ line.boundingBox?.let { putMap("frame", rectToMap(it)) }
81
+ line.cornerPoints?.let { putArray("cornerPoints", cornerPointsToMap(it)) }
82
+ putArray("recognizedLanguages", langToMap(line.recognizedLanguage))
83
+
84
+ val elementsArray = Arguments.createArray()
85
+ line.elements.forEach { element ->
86
+ elementsArray.pushMap(Arguments.createMap().apply {
87
+ putString("text", element.text)
88
+ element.boundingBox?.let { putMap("frame", rectToMap(it)) }
89
+ element.cornerPoints?.let { putArray("cornerPoints", cornerPointsToMap(it)) }
90
+ })
91
+ }
92
+ putArray("elements", elementsArray)
93
+ }
94
+ }
95
+
96
+ private fun blockToMap(block: Text.TextBlock): WritableMap {
97
+ return Arguments.createMap().apply {
98
+ putString("text", block.text)
99
+ block.boundingBox?.let { putMap("frame", rectToMap(it)) }
100
+ block.cornerPoints?.let { putArray("cornerPoints", cornerPointsToMap(it)) }
101
+
102
+ val linesArray = Arguments.createArray()
103
+ block.lines.forEach { line ->
104
+ linesArray.pushMap(lineToMap(line))
105
+ }
106
+ putArray("lines", linesArray)
107
+ putArray("recognizedLanguages", langToMap(block.recognizedLanguage))
108
+ }
109
+ }
110
+
111
+ @NonNull
112
+ private fun getScriptTextRecognizerOptions(@Nullable script: String?): TextRecognizerOptionsInterface {
113
+ return when (script) {
114
+ "Chinese" -> ChineseTextRecognizerOptions.Builder().build()
115
+ "Devanagari" -> DevanagariTextRecognizerOptions.Builder().build()
116
+ "Japanese" -> JapaneseTextRecognizerOptions.Builder().build()
117
+ "Korean" -> KoreanTextRecognizerOptions.Builder().build()
118
+ else -> TextRecognizerOptions.DEFAULT_OPTIONS
119
+ }
120
+ }
121
+
122
+ @ReactMethod
123
+ fun read(url: String, script: ReadableMap?, promise: Promise) {
124
+ try {
125
+ val image = getInputImage(reactApplicationContext, url)
126
+
127
+ val options = getScriptTextRecognizerOptions(script.toString())
128
+
129
+ val recognizer: TextRecognizer = TextRecognition.getClient(options)
130
+
131
+ recognizer.process(image)
132
+ .addOnSuccessListener { visionText ->
133
+ val result = Arguments.createMap()
134
+ result.putString("text", visionText.text)
135
+
136
+ val blocksArray = Arguments.createArray()
137
+ visionText.textBlocks.forEach { block ->
138
+ blocksArray.pushMap(blockToMap(block))
139
+ }
140
+ result.putArray("blocks", blocksArray)
10
141
 
11
- override fun getName(): String {
12
- return NAME
13
- }
14
-
15
- // Example method
16
- // See https://reactnative.dev/docs/native-modules-android
17
- @ReactMethod
18
- fun multiply(a: Double, b: Double, promise: Promise) {
19
- promise.resolve(a * b)
20
- }
21
-
22
- companion object {
23
- const val NAME = "TextReader"
24
- }
25
- }
142
+ promise.resolve(result)
143
+ }
144
+ .addOnFailureListener { e ->
145
+ e.printStackTrace()
146
+ promise.reject("Text recognition failed", e)
147
+ }
148
+ } catch (e: IOException) {
149
+ e.printStackTrace()
150
+ promise.reject("Text recognition failed", e)
151
+ }
152
+ }
153
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-text-reader",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "A React Native library for OCR (Optical Character Recognition) using Vision Framework on iOS and Firebase ML Kit on Android.",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/commonjs/index.js",