react-native-text-reader 2.0.1 → 2.1.1

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.
package/README.md CHANGED
@@ -103,9 +103,53 @@ const result = await TextReader.readDetailed(imagePath, {
103
103
 
104
104
  console.log(result.fullText);
105
105
  console.log(result.lines);
106
- console.log(result.details); // confidence, frame, languages
106
+ console.log(result.details); // confidence, box, words, languages
107
107
  ```
108
108
 
109
+ ### Documents (ID cards, forms)
110
+
111
+ `readDocument()` applies the settings that printed documents need: `accurate`
112
+ recognition, **language correction off** — it would otherwise push codes like an
113
+ MRZ or a Mexican CURP toward dictionary words — and word-level boxes.
114
+
115
+ ```typescript
116
+ const result = await TextReader.readDocument(imagePath);
117
+
118
+ for (const line of result.details) {
119
+ console.log(line.text, line.box); // { x, y, width, height }, 0-1
120
+ for (const word of line.words ?? []) {
121
+ console.log(' ', word.text, word.box);
122
+ }
123
+ }
124
+ ```
125
+
126
+ ### Layout: `box` vs `frame`
127
+
128
+ `box` is a normalized rect (`0-1`) with a **top-left origin**, identical on both
129
+ platforms. Use it to reason about layout — columns, reading order, which value
130
+ sits under which label:
131
+
132
+ ```typescript
133
+ // Value in the same column as its label, rather than "the next line"
134
+ const label = result.details.find((line) => line.text.includes('VIGENCIA'));
135
+ const value = result.details.find(
136
+ (line) =>
137
+ line.box && label?.box &&
138
+ line.box.y > label.box.y &&
139
+ Math.abs(line.box.x - label.box.x) < 0.05
140
+ );
141
+ ```
142
+
143
+ > `frame` is **deprecated**. Its units and origin differ per platform (iOS:
144
+ > normalized ×1000, bottom-left; Android: pixels, top-left), so it was never
145
+ > comparable across platforms. It still ships unchanged for existing callers.
146
+
147
+ ### Confidence
148
+
149
+ `confidence` is `undefined` when the engine reports no value — it is never
150
+ filled in with a placeholder. Absence of a measurement is not a low
151
+ measurement, and a fabricated `1.0` reads downstream as maximum certainty.
152
+
109
153
  ## Options
110
154
 
111
155
  | Property | Type | Platform | Description |
@@ -118,6 +162,8 @@ console.log(result.details); // confidence, frame, languages
118
162
  | `customWords` | `string[]` | iOS | Domain vocabulary hints |
119
163
  | `useLanguageCorrection` | `boolean` | iOS | Enable language correction |
120
164
  | `minimumTextHeight` | `number` | iOS | Ignore text smaller than this fraction |
165
+ | `includeWords` | `boolean` | Both | Return each word with its own `box` and confidence |
166
+ | `regionOfInterest` | `TextBox` | Both | Restrict recognition to a normalized area (`0-1`, top-left origin) |
121
167
 
122
168
  ## ScriptOptions
123
169
 
@@ -38,35 +38,65 @@ class TextReaderModule(reactContext: ReactApplicationContext) :
38
38
  override fun getName(): String = "TextReader"
39
39
 
40
40
  @Throws(IOException::class)
41
- private fun getInputImage(reactContext: ReactApplicationContext, url: String): InputImage {
42
- return if (url.contains("http://") || url.contains("https://")) {
43
- val connection = URL(url).openConnection() as HttpURLConnection
44
- connection.connectTimeout = HTTP_CONNECT_TIMEOUT_MS
45
- connection.readTimeout = HTTP_READ_TIMEOUT_MS
46
- connection.connect()
47
-
48
- val contentLength = connection.contentLength
49
- if (contentLength > MAX_IMAGE_BYTES) {
50
- connection.disconnect()
51
- throw IOException("Remote image exceeds maximum allowed size.")
52
- }
41
+ private fun remoteBitmap(url: String): Bitmap {
42
+ val connection = URL(url).openConnection() as HttpURLConnection
43
+ connection.connectTimeout = HTTP_CONNECT_TIMEOUT_MS
44
+ connection.readTimeout = HTTP_READ_TIMEOUT_MS
45
+ connection.connect()
53
46
 
54
- val image: Bitmap? = connection.inputStream.use { stream ->
55
- BitmapFactory.decodeStream(stream)
56
- }
47
+ val contentLength = connection.contentLength
48
+ if (contentLength > MAX_IMAGE_BYTES) {
57
49
  connection.disconnect()
50
+ throw IOException("Remote image exceeds maximum allowed size.")
51
+ }
58
52
 
59
- if (image == null) {
60
- throw IOException("Failed to decode remote image.")
61
- }
53
+ val image: Bitmap? = connection.inputStream.use { stream ->
54
+ BitmapFactory.decodeStream(stream)
55
+ }
56
+ connection.disconnect()
62
57
 
63
- InputImage.fromBitmap(image, 0)
58
+ return image ?: throw IOException("Failed to decode remote image.")
59
+ }
60
+
61
+ @Throws(IOException::class)
62
+ private fun getInputImage(reactContext: ReactApplicationContext, url: String): InputImage {
63
+ return if (url.contains("http://") || url.contains("https://")) {
64
+ InputImage.fromBitmap(remoteBitmap(url), 0)
64
65
  } else {
65
66
  val uri = Uri.parse(url)
66
67
  InputImage.fromFilePath(reactContext, uri)
67
68
  }
68
69
  }
69
70
 
71
+ private fun croppedInputImage(
72
+ reactContext: ReactApplicationContext,
73
+ url: String,
74
+ region: ReadableMap
75
+ ): InputImage {
76
+ val bitmap = loadBitmap(reactContext, url)
77
+ val x = (region.getDouble("x") * bitmap.width).toInt().coerceIn(0, bitmap.width - 1)
78
+ val y = (region.getDouble("y") * bitmap.height).toInt().coerceIn(0, bitmap.height - 1)
79
+ val width = (region.getDouble("width") * bitmap.width).toInt()
80
+ .coerceIn(1, bitmap.width - x)
81
+ val height = (region.getDouble("height") * bitmap.height).toInt()
82
+ .coerceIn(1, bitmap.height - y)
83
+
84
+ return InputImage.fromBitmap(Bitmap.createBitmap(bitmap, x, y, width, height), 0)
85
+ }
86
+
87
+ @Throws(IOException::class)
88
+ private fun loadBitmap(reactContext: ReactApplicationContext, url: String): Bitmap {
89
+ if (url.contains("http://") || url.contains("https://")) {
90
+ return remoteBitmap(url)
91
+ }
92
+
93
+ val stream = reactContext.contentResolver.openInputStream(Uri.parse(url))
94
+ ?: throw IOException("Could not open image at $url")
95
+
96
+ return stream.use { BitmapFactory.decodeStream(it) }
97
+ ?: throw IOException("Failed to decode image at $url")
98
+ }
99
+
70
100
  private fun rectToMap(rect: Rect): WritableMap {
71
101
  return Arguments.createMap().apply {
72
102
  putInt("width", rect.width())
@@ -95,24 +125,37 @@ class TextReaderModule(reactContext: ReactApplicationContext) :
95
125
  }
96
126
  }
97
127
 
98
- private fun lineConfidence(line: Text.Line): Float {
99
- val elements = line.elements
100
- if (elements.isEmpty()) return 1.0f
101
- return elements.map { element ->
102
- try {
103
- val method = element.javaClass.getMethod("getConfidence")
104
- (method.invoke(element) as? Float) ?: 1.0f
105
- } catch (_: Exception) {
106
- 1.0f
107
- }
108
- }.average().toFloat()
128
+ private fun lineConfidence(line: Text.Line): Float? {
129
+ val confidences = line.elements.mapNotNull { it.confidence }
130
+ if (confidences.isEmpty()) {
131
+ return null
132
+ }
133
+ return confidences.average().toFloat()
134
+ }
135
+
136
+ private fun normalizedBox(rect: Rect?, width: Int, height: Int): WritableMap? {
137
+ if (rect == null || width <= 0 || height <= 0) {
138
+ return null
139
+ }
140
+ return Arguments.createMap().apply {
141
+ putDouble("x", rect.left.toDouble() / width)
142
+ putDouble("y", rect.top.toDouble() / height)
143
+ putDouble("width", rect.width().toDouble() / width)
144
+ putDouble("height", rect.height().toDouble() / height)
145
+ }
109
146
  }
110
147
 
111
- private fun lineToMap(line: Text.Line): WritableMap {
148
+ private fun lineToMap(
149
+ line: Text.Line,
150
+ imageWidth: Int,
151
+ imageHeight: Int,
152
+ includeWords: Boolean
153
+ ): WritableMap {
112
154
  return Arguments.createMap().apply {
113
155
  putString("text", line.text)
114
- putDouble("confidence", lineConfidence(line).toDouble())
156
+ lineConfidence(line)?.let { putDouble("confidence", it.toDouble()) }
115
157
  line.boundingBox?.let { putMap("frame", rectToMap(it)) }
158
+ normalizedBox(line.boundingBox, imageWidth, imageHeight)?.let { putMap("box", it) }
116
159
  line.cornerPoints?.let { putArray("cornerPoints", cornerPointsToMap(it)) }
117
160
  putArray("recognizedLanguages", langToMap(line.recognizedLanguage))
118
161
 
@@ -125,21 +168,20 @@ class TextReaderModule(reactContext: ReactApplicationContext) :
125
168
  })
126
169
  }
127
170
  putArray("elements", elementsArray)
128
- }
129
- }
130
171
 
131
- private fun blockToMap(block: Text.TextBlock): WritableMap {
132
- return Arguments.createMap().apply {
133
- putString("text", block.text)
134
- block.boundingBox?.let { putMap("frame", rectToMap(it)) }
135
- block.cornerPoints?.let { putArray("cornerPoints", cornerPointsToMap(it)) }
136
-
137
- val linesArray = Arguments.createArray()
138
- block.lines.forEach { line ->
139
- linesArray.pushMap(lineToMap(line))
172
+ if (includeWords) {
173
+ val wordsArray = Arguments.createArray()
174
+ line.elements.forEach { element ->
175
+ wordsArray.pushMap(Arguments.createMap().apply {
176
+ putString("text", element.text)
177
+ normalizedBox(element.boundingBox, imageWidth, imageHeight)?.let {
178
+ putMap("box", it)
179
+ }
180
+ element.confidence?.let { putDouble("confidence", it.toDouble()) }
181
+ })
182
+ }
183
+ putArray("words", wordsArray)
140
184
  }
141
- putArray("lines", linesArray)
142
- putArray("recognizedLanguages", langToMap(block.recognizedLanguage))
143
185
  }
144
186
  }
145
187
 
@@ -157,7 +199,7 @@ class TextReaderModule(reactContext: ReactApplicationContext) :
157
199
  private fun sortedLines(visionText: Text, confidenceThreshold: Float): List<Text.Line> {
158
200
  return visionText.textBlocks
159
201
  .flatMap { block -> block.lines }
160
- .filter { line -> lineConfidence(line) >= confidenceThreshold }
202
+ .filter { line -> (lineConfidence(line) ?: Float.MAX_VALUE) >= confidenceThreshold }
161
203
  .sortedWith(compareBy({ it.boundingBox?.top ?: 0 }, { it.boundingBox?.left ?: 0 }))
162
204
  }
163
205
 
@@ -179,15 +221,36 @@ class TextReaderModule(reactContext: ReactApplicationContext) :
179
221
  0.0f
180
222
  }
181
223
 
224
+ val includeWords = options?.hasKey("includeWords") == true &&
225
+ options.getBoolean("includeWords")
226
+
182
227
  val recognizer: TextRecognizer = TextRecognition.getClient(getScriptTextRecognizerOptions(script))
183
228
 
184
229
  try {
185
- val image = getInputImage(reactApplicationContext, url)
230
+ val region = if (options?.hasKey("regionOfInterest") == true) {
231
+ options.getMap("regionOfInterest")
232
+ } else {
233
+ null
234
+ }
235
+ val image = if (region != null) {
236
+ croppedInputImage(reactApplicationContext, url, region)
237
+ } else {
238
+ getInputImage(reactApplicationContext, url)
239
+ }
240
+
186
241
  recognizer.process(image)
187
242
  .addOnSuccessListener { visionText ->
188
243
  val lines = sortedLines(visionText, confidenceThreshold)
189
244
  if (detailed) {
190
- promise.resolve(buildDetailedResult(visionText, lines))
245
+ promise.resolve(
246
+ buildDetailedResult(
247
+ visionText,
248
+ lines,
249
+ image.width,
250
+ image.height,
251
+ includeWords
252
+ )
253
+ )
191
254
  } else {
192
255
  val linesArray = Arguments.createArray()
193
256
  lines.forEach { line -> linesArray.pushString(line.text) }
@@ -209,11 +272,17 @@ class TextReaderModule(reactContext: ReactApplicationContext) :
209
272
  }
210
273
  }
211
274
 
212
- private fun buildDetailedResult(visionText: Text, lines: List<Text.Line>): WritableMap {
275
+ private fun buildDetailedResult(
276
+ visionText: Text,
277
+ lines: List<Text.Line>,
278
+ imageWidth: Int,
279
+ imageHeight: Int,
280
+ includeWords: Boolean
281
+ ): WritableMap {
213
282
  val lineTexts = lines.map { it.text }
214
283
  val detailsArray = Arguments.createArray()
215
284
  lines.forEach { line ->
216
- detailsArray.pushMap(lineToMap(line))
285
+ detailsArray.pushMap(lineToMap(line, imageWidth, imageHeight, includeWords))
217
286
  }
218
287
 
219
288
  return Arguments.createMap().apply {
@@ -222,6 +291,7 @@ class TextReaderModule(reactContext: ReactApplicationContext) :
222
291
  lineTexts.forEach { pushString(it) }
223
292
  })
224
293
  putArray("details", detailsArray)
294
+ putString("coordinateSpace", "normalized-top-left")
225
295
  }
226
296
  }
227
297
 
@@ -8,10 +8,26 @@ extension String {
8
8
  }
9
9
  }
10
10
 
11
+ private struct RecognizedWord {
12
+ let text: String
13
+ let confidence: Float
14
+ let box: CGRect
15
+ }
16
+
11
17
  private struct RecognizedLine {
12
18
  let text: String
13
19
  let confidence: Float
14
20
  let frame: CGRect
21
+ let words: [RecognizedWord]
22
+ }
23
+
24
+ private func normalizedBoxPayload(_ box: CGRect) -> [String: Any] {
25
+ return [
26
+ "x": box.origin.x,
27
+ "y": 1.0 - box.origin.y - box.height,
28
+ "width": box.width,
29
+ "height": box.height,
30
+ ]
15
31
  }
16
32
 
17
33
  private struct TextCandidate {
@@ -54,6 +70,7 @@ class TextReader: NSObject {
54
70
  switch result {
55
71
  case .success(let lines):
56
72
  let lineTexts = lines.map { $0.text }
73
+ let includeWords = (options["includeWords"] as? Bool) ?? false
57
74
  let details: [[String: Any]] = lines.map { line in
58
75
  var detail: [String: Any] = [
59
76
  "text": line.text,
@@ -65,12 +82,23 @@ class TextReader: NSObject {
65
82
  "width": Int(line.frame.width * 1000),
66
83
  "height": Int(line.frame.height * 1000),
67
84
  ]
85
+ detail["box"] = normalizedBoxPayload(line.frame)
86
+ if includeWords {
87
+ detail["words"] = line.words.map { word in
88
+ [
89
+ "text": word.text,
90
+ "confidence": word.confidence,
91
+ "box": normalizedBoxPayload(word.box),
92
+ ] as [String: Any]
93
+ }
94
+ }
68
95
  return detail
69
96
  }
70
97
  resolve([
71
98
  "fullText": lineTexts.joined(separator: "\n"),
72
99
  "lines": lineTexts,
73
100
  "details": details,
101
+ "coordinateSpace": "normalized-top-left",
74
102
  ])
75
103
  case .failure(let error):
76
104
  reject(error.code, error.message, error.underlying)
@@ -150,6 +178,19 @@ class TextReader: NSObject {
150
178
  request.recognitionLanguages = languages
151
179
  }
152
180
 
181
+ if let roi = options["regionOfInterest"] as? [String: Any],
182
+ let x = roi["x"] as? NSNumber,
183
+ let y = roi["y"] as? NSNumber,
184
+ let width = roi["width"] as? NSNumber,
185
+ let height = roi["height"] as? NSNumber {
186
+ request.regionOfInterest = CGRect(
187
+ x: CGFloat(truncating: x),
188
+ y: 1.0 - CGFloat(truncating: y) - CGFloat(truncating: height),
189
+ width: CGFloat(truncating: width),
190
+ height: CGFloat(truncating: height)
191
+ )
192
+ }
193
+
153
194
  if let customWords = options["customWords"] as? [String], !customWords.isEmpty {
154
195
  request.customWords = customWords
155
196
  }
@@ -228,6 +269,9 @@ class TextReader: NSObject {
228
269
  let maxX = sortedGroup.map { $0.box.maxX }.max() ?? 0
229
270
  let maxY = sortedGroup.map { $0.box.maxY }.max() ?? 0
230
271
  let frame = CGRect(x: minX, y: minY, width: maxX - minX, height: maxY - minY)
231
- return RecognizedLine(text: text, confidence: confidence, frame: frame)
272
+ let words = sortedGroup.map {
273
+ RecognizedWord(text: $0.text, confidence: $0.confidence, box: $0.box)
274
+ }
275
+ return RecognizedLine(text: text, confidence: confidence, frame: frame, words: words)
232
276
  }
233
277
  }
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_default","exports","default","TurboModuleRegistry","get"],"sourceRoot":"../../src","sources":["NativeTextReader.ts"],"mappings":";;;;;;AACA,IAAAA,YAAA,GAAAC,OAAA;AAAmD,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAuCpCC,gCAAmB,CAACC,GAAG,CAAO,YAAY,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_default","exports","default","TurboModuleRegistry","get"],"sourceRoot":"../../src","sources":["NativeTextReader.ts"],"mappings":";;;;;;AACA,IAAAA,YAAA,GAAAC,OAAA;AAAmD,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GA8DpCC,gCAAmB,CAACC,GAAG,CAAO,YAAY,CAAC","ignoreList":[]}
@@ -25,6 +25,10 @@ let ScriptOptions = exports.ScriptOptions = /*#__PURE__*/function (ScriptOptions
25
25
  ScriptOptions["KOREAN"] = "Korean";
26
26
  return ScriptOptions;
27
27
  }({});
28
+ /**
29
+ * @deprecated Sus unidades y su origen difieren entre plataformas, así que no
30
+ * es comparable cross-platform. Usa `TextLine.box`.
31
+ */
28
32
  const DEFAULT_OPTIONS = {
29
33
  script: ScriptOptions.LATIN
30
34
  };
@@ -32,14 +36,24 @@ function normalizeDetailedResult(result) {
32
36
  return {
33
37
  fullText: result.fullText ?? '',
34
38
  lines: result.lines ?? [],
39
+ coordinateSpace: result.coordinateSpace,
35
40
  details: (result.details ?? []).map(detail => ({
36
41
  text: detail.text,
37
42
  confidence: detail.confidence,
38
43
  frame: detail.frame,
44
+ box: detail.box,
45
+ words: detail.words,
39
46
  recognizedLanguages: detail.recognizedLanguages
40
47
  }))
41
48
  };
42
49
  }
50
+ const DOCUMENT_OPTIONS = {
51
+ script: ScriptOptions.LATIN,
52
+ recognitionLevel: 'accurate',
53
+ useLanguageCorrection: false,
54
+ minimumTextHeight: 0.008,
55
+ includeWords: true
56
+ };
43
57
 
44
58
  /**
45
59
  * Extracts text lines from an image.
@@ -56,8 +70,15 @@ async function readDetailed(imagePath, options) {
56
70
  const result = await TextReader.readDetailed(imagePath, options ?? DEFAULT_OPTIONS);
57
71
  return normalizeDetailedResult(result);
58
72
  }
73
+ async function readDocument(imagePath, options) {
74
+ return readDetailed(imagePath, {
75
+ ...DOCUMENT_OPTIONS,
76
+ ...options
77
+ });
78
+ }
59
79
  var _default = exports.default = {
60
80
  read,
61
- readDetailed
81
+ readDetailed,
82
+ readDocument
62
83
  };
63
84
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_NativeTextReader","_interopRequireDefault","e","__esModule","default","LINKING_ERROR","Platform","select","ios","TextReaderModule","NativeTextReaderModule","NativeModules","TextReader","Proxy","get","Error","ScriptOptions","exports","DEFAULT_OPTIONS","script","LATIN","normalizeDetailedResult","result","fullText","lines","details","map","detail","text","confidence","frame","recognizedLanguages","read","imagePath","options","detailed","readDetailed","_default"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,iBAAA,GAAAC,sBAAA,CAAAF,OAAA;AAAwD,SAAAE,uBAAAC,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAExD,MAAMG,aAAa,GACjB,mFAAmF,GACnFC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEJ,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,iEAAiE;AAEnE,MAAMK,gBAAgB,GAAGC,yBAAsB,IAAIC,0BAAa,CAACC,UAAU;AAE3E,MAAMA,UAAU,GAAGH,gBAAgB,GAC/BA,gBAAgB,GAChB,IAAII,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACV,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAAC,IAEMW,aAAa,GAAAC,OAAA,CAAAD,aAAA,0BAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAA,OAAbA,aAAa;AAAA;AA8CzB,MAAME,eAAwB,GAAG;EAC/BC,MAAM,EAAEH,aAAa,CAACI;AACxB,CAAC;AAED,SAASC,uBAAuBA,CAACC,MAAsB,EAAkB;EACvE,OAAO;IACLC,QAAQ,EAAED,MAAM,CAACC,QAAQ,IAAI,EAAE;IAC/BC,KAAK,EAAEF,MAAM,CAACE,KAAK,IAAI,EAAE;IACzBC,OAAO,EAAE,CAACH,MAAM,CAACG,OAAO,IAAI,EAAE,EAAEC,GAAG,CAAEC,MAAM,KAAM;MAC/CC,IAAI,EAAED,MAAM,CAACC,IAAI;MACjBC,UAAU,EAAEF,MAAM,CAACE,UAAU;MAC7BC,KAAK,EAAEH,MAAM,CAACG,KAAK;MACnBC,mBAAmB,EAAEJ,MAAM,CAACI;IAC9B,CAAC,CAAC;EACJ,CAAC;AACH;;AAEA;AACA;AACA;AACA,eAAeC,IAAIA,CAACC,SAAiB,EAAEC,OAAiB,EAAqB;EAC3E,MAAMC,QAAQ,GAAG,MAAMC,YAAY,CAACH,SAAS,EAAEC,OAAO,CAAC;EACvD,OAAOC,QAAQ,CAACX,KAAK;AACvB;;AAEA;AACA;AACA;AACA,eAAeY,YAAYA,CACzBH,SAAiB,EACjBC,OAAiB,EACQ;EACzB,MAAMZ,MAAM,GAAG,MAAMV,UAAU,CAACwB,YAAY,CAC1CH,SAAS,EACTC,OAAO,IAAIhB,eACb,CAAC;EACD,OAAOG,uBAAuB,CAACC,MAAM,CAAC;AACxC;AAAC,IAAAe,QAAA,GAAApB,OAAA,CAAAb,OAAA,GAEc;EAAE4B,IAAI;EAAEI;AAAa,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_NativeTextReader","_interopRequireDefault","e","__esModule","default","LINKING_ERROR","Platform","select","ios","TextReaderModule","NativeTextReaderModule","NativeModules","TextReader","Proxy","get","Error","ScriptOptions","exports","DEFAULT_OPTIONS","script","LATIN","normalizeDetailedResult","result","fullText","lines","coordinateSpace","details","map","detail","text","confidence","frame","box","words","recognizedLanguages","DOCUMENT_OPTIONS","recognitionLevel","useLanguageCorrection","minimumTextHeight","includeWords","read","imagePath","options","detailed","readDetailed","readDocument","_default"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AACA,IAAAC,iBAAA,GAAAC,sBAAA,CAAAF,OAAA;AAAwD,SAAAE,uBAAAC,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAExD,MAAMG,aAAa,GACjB,mFAAmF,GACnFC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEJ,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,iEAAiE;AAEnE,MAAMK,gBAAgB,GAAGC,yBAAsB,IAAIC,0BAAa,CAACC,UAAU;AAE3E,MAAMA,UAAU,GAAGH,gBAAgB,GAC/BA,gBAAgB,GAChB,IAAII,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACV,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAAC,IAEMW,aAAa,GAAAC,OAAA,CAAAD,aAAA,0BAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAA,OAAbA,aAAa;AAAA;AAUzB;AACA;AACA;AACA;AAoEA,MAAME,eAAwB,GAAG;EAC/BC,MAAM,EAAEH,aAAa,CAACI;AACxB,CAAC;AAED,SAASC,uBAAuBA,CAACC,MAAsB,EAAkB;EACvE,OAAO;IACLC,QAAQ,EAAED,MAAM,CAACC,QAAQ,IAAI,EAAE;IAC/BC,KAAK,EAAEF,MAAM,CAACE,KAAK,IAAI,EAAE;IACzBC,eAAe,EAAEH,MAAM,CAACG,eAAe;IACvCC,OAAO,EAAE,CAACJ,MAAM,CAACI,OAAO,IAAI,EAAE,EAAEC,GAAG,CAAEC,MAAM,KAAM;MAC/CC,IAAI,EAAED,MAAM,CAACC,IAAI;MACjBC,UAAU,EAAEF,MAAM,CAACE,UAAU;MAC7BC,KAAK,EAAEH,MAAM,CAACG,KAAK;MACnBC,GAAG,EAAEJ,MAAM,CAACI,GAAG;MACfC,KAAK,EAAEL,MAAM,CAACK,KAAK;MACnBC,mBAAmB,EAAEN,MAAM,CAACM;IAC9B,CAAC,CAAC;EACJ,CAAC;AACH;AAEA,MAAMC,gBAAyB,GAAG;EAChChB,MAAM,EAAEH,aAAa,CAACI,KAAK;EAC3BgB,gBAAgB,EAAE,UAAU;EAC5BC,qBAAqB,EAAE,KAAK;EAC5BC,iBAAiB,EAAE,KAAK;EACxBC,YAAY,EAAE;AAChB,CAAC;;AAED;AACA;AACA;AACA,eAAeC,IAAIA,CAACC,SAAiB,EAAEC,OAAiB,EAAqB;EAC3E,MAAMC,QAAQ,GAAG,MAAMC,YAAY,CAACH,SAAS,EAAEC,OAAO,CAAC;EACvD,OAAOC,QAAQ,CAACnB,KAAK;AACvB;;AAEA;AACA;AACA;AACA,eAAeoB,YAAYA,CACzBH,SAAiB,EACjBC,OAAiB,EACQ;EACzB,MAAMpB,MAAM,GAAG,MAAMV,UAAU,CAACgC,YAAY,CAC1CH,SAAS,EACTC,OAAO,IAAIxB,eACb,CAAC;EACD,OAAOG,uBAAuB,CAACC,MAAM,CAAC;AACxC;AAEA,eAAeuB,YAAYA,CACzBJ,SAAiB,EACjBC,OAAiB,EACQ;EACzB,OAAOE,YAAY,CAACH,SAAS,EAAE;IAAE,GAAGN,gBAAgB;IAAE,GAAGO;EAAQ,CAAC,CAAC;AACrE;AAAC,IAAAI,QAAA,GAAA7B,OAAA,CAAAb,OAAA,GAEc;EAAEoC,IAAI;EAAEI,YAAY;EAAEC;AAAa,CAAC","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["TurboModuleRegistry","get"],"sourceRoot":"../../src","sources":["NativeTextReader.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AAuClD,eAAeA,mBAAmB,CAACC,GAAG,CAAO,YAAY,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["TurboModuleRegistry","get"],"sourceRoot":"../../src","sources":["NativeTextReader.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AA8DlD,eAAeA,mBAAmB,CAACC,GAAG,CAAO,YAAY,CAAC","ignoreList":[]}
@@ -20,6 +20,12 @@ export let ScriptOptions = /*#__PURE__*/function (ScriptOptions) {
20
20
  ScriptOptions["KOREAN"] = "Korean";
21
21
  return ScriptOptions;
22
22
  }({});
23
+
24
+ /**
25
+ * @deprecated Sus unidades y su origen difieren entre plataformas, así que no
26
+ * es comparable cross-platform. Usa `TextLine.box`.
27
+ */
28
+
23
29
  const DEFAULT_OPTIONS = {
24
30
  script: ScriptOptions.LATIN
25
31
  };
@@ -27,14 +33,24 @@ function normalizeDetailedResult(result) {
27
33
  return {
28
34
  fullText: result.fullText ?? '',
29
35
  lines: result.lines ?? [],
36
+ coordinateSpace: result.coordinateSpace,
30
37
  details: (result.details ?? []).map(detail => ({
31
38
  text: detail.text,
32
39
  confidence: detail.confidence,
33
40
  frame: detail.frame,
41
+ box: detail.box,
42
+ words: detail.words,
34
43
  recognizedLanguages: detail.recognizedLanguages
35
44
  }))
36
45
  };
37
46
  }
47
+ const DOCUMENT_OPTIONS = {
48
+ script: ScriptOptions.LATIN,
49
+ recognitionLevel: 'accurate',
50
+ useLanguageCorrection: false,
51
+ minimumTextHeight: 0.008,
52
+ includeWords: true
53
+ };
38
54
 
39
55
  /**
40
56
  * Extracts text lines from an image.
@@ -51,8 +67,15 @@ async function readDetailed(imagePath, options) {
51
67
  const result = await TextReader.readDetailed(imagePath, options ?? DEFAULT_OPTIONS);
52
68
  return normalizeDetailedResult(result);
53
69
  }
70
+ async function readDocument(imagePath, options) {
71
+ return readDetailed(imagePath, {
72
+ ...DOCUMENT_OPTIONS,
73
+ ...options
74
+ });
75
+ }
54
76
  export default {
55
77
  read,
56
- readDetailed
78
+ readDetailed,
79
+ readDocument
57
80
  };
58
81
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["NativeModules","Platform","NativeTextReaderModule","LINKING_ERROR","select","ios","default","TextReaderModule","TextReader","Proxy","get","Error","ScriptOptions","DEFAULT_OPTIONS","script","LATIN","normalizeDetailedResult","result","fullText","lines","details","map","detail","text","confidence","frame","recognizedLanguages","read","imagePath","options","detailed","readDetailed"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AACtD,OAAOC,sBAAsB,MAAM,uBAAoB;AAEvD,MAAMC,aAAa,GACjB,mFAAmF,GACnFF,QAAQ,CAACG,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,iEAAiE;AAEnE,MAAMC,gBAAgB,GAAGL,sBAAsB,IAAIF,aAAa,CAACQ,UAAU;AAE3E,MAAMA,UAAU,GAAGD,gBAAgB,GAC/BA,gBAAgB,GAChB,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACR,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEL,WAAYS,aAAa,0BAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAA,OAAbA,aAAa;AAAA;AA8CzB,MAAMC,eAAwB,GAAG;EAC/BC,MAAM,EAAEF,aAAa,CAACG;AACxB,CAAC;AAED,SAASC,uBAAuBA,CAACC,MAAsB,EAAkB;EACvE,OAAO;IACLC,QAAQ,EAAED,MAAM,CAACC,QAAQ,IAAI,EAAE;IAC/BC,KAAK,EAAEF,MAAM,CAACE,KAAK,IAAI,EAAE;IACzBC,OAAO,EAAE,CAACH,MAAM,CAACG,OAAO,IAAI,EAAE,EAAEC,GAAG,CAAEC,MAAM,KAAM;MAC/CC,IAAI,EAAED,MAAM,CAACC,IAAI;MACjBC,UAAU,EAAEF,MAAM,CAACE,UAAU;MAC7BC,KAAK,EAAEH,MAAM,CAACG,KAAK;MACnBC,mBAAmB,EAAEJ,MAAM,CAACI;IAC9B,CAAC,CAAC;EACJ,CAAC;AACH;;AAEA;AACA;AACA;AACA,eAAeC,IAAIA,CAACC,SAAiB,EAAEC,OAAiB,EAAqB;EAC3E,MAAMC,QAAQ,GAAG,MAAMC,YAAY,CAACH,SAAS,EAAEC,OAAO,CAAC;EACvD,OAAOC,QAAQ,CAACX,KAAK;AACvB;;AAEA;AACA;AACA;AACA,eAAeY,YAAYA,CACzBH,SAAiB,EACjBC,OAAiB,EACQ;EACzB,MAAMZ,MAAM,GAAG,MAAMT,UAAU,CAACuB,YAAY,CAC1CH,SAAS,EACTC,OAAO,IAAIhB,eACb,CAAC;EACD,OAAOG,uBAAuB,CAACC,MAAM,CAAC;AACxC;AAEA,eAAe;EAAEU,IAAI;EAAEI;AAAa,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["NativeModules","Platform","NativeTextReaderModule","LINKING_ERROR","select","ios","default","TextReaderModule","TextReader","Proxy","get","Error","ScriptOptions","DEFAULT_OPTIONS","script","LATIN","normalizeDetailedResult","result","fullText","lines","coordinateSpace","details","map","detail","text","confidence","frame","box","words","recognizedLanguages","DOCUMENT_OPTIONS","recognitionLevel","useLanguageCorrection","minimumTextHeight","includeWords","read","imagePath","options","detailed","readDetailed","readDocument"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AACtD,OAAOC,sBAAsB,MAAM,uBAAoB;AAEvD,MAAMC,aAAa,GACjB,mFAAmF,GACnFF,QAAQ,CAACG,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,iEAAiE;AAEnE,MAAMC,gBAAgB,GAAGL,sBAAsB,IAAIF,aAAa,CAACQ,UAAU;AAE3E,MAAMA,UAAU,GAAGD,gBAAgB,GAC/BA,gBAAgB,GAChB,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACR,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEL,WAAYS,aAAa,0BAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAA,OAAbA,aAAa;AAAA;;AAUzB;AACA;AACA;AACA;;AAoEA,MAAMC,eAAwB,GAAG;EAC/BC,MAAM,EAAEF,aAAa,CAACG;AACxB,CAAC;AAED,SAASC,uBAAuBA,CAACC,MAAsB,EAAkB;EACvE,OAAO;IACLC,QAAQ,EAAED,MAAM,CAACC,QAAQ,IAAI,EAAE;IAC/BC,KAAK,EAAEF,MAAM,CAACE,KAAK,IAAI,EAAE;IACzBC,eAAe,EAAEH,MAAM,CAACG,eAAe;IACvCC,OAAO,EAAE,CAACJ,MAAM,CAACI,OAAO,IAAI,EAAE,EAAEC,GAAG,CAAEC,MAAM,KAAM;MAC/CC,IAAI,EAAED,MAAM,CAACC,IAAI;MACjBC,UAAU,EAAEF,MAAM,CAACE,UAAU;MAC7BC,KAAK,EAAEH,MAAM,CAACG,KAAK;MACnBC,GAAG,EAAEJ,MAAM,CAACI,GAAG;MACfC,KAAK,EAAEL,MAAM,CAACK,KAAK;MACnBC,mBAAmB,EAAEN,MAAM,CAACM;IAC9B,CAAC,CAAC;EACJ,CAAC;AACH;AAEA,MAAMC,gBAAyB,GAAG;EAChChB,MAAM,EAAEF,aAAa,CAACG,KAAK;EAC3BgB,gBAAgB,EAAE,UAAU;EAC5BC,qBAAqB,EAAE,KAAK;EAC5BC,iBAAiB,EAAE,KAAK;EACxBC,YAAY,EAAE;AAChB,CAAC;;AAED;AACA;AACA;AACA,eAAeC,IAAIA,CAACC,SAAiB,EAAEC,OAAiB,EAAqB;EAC3E,MAAMC,QAAQ,GAAG,MAAMC,YAAY,CAACH,SAAS,EAAEC,OAAO,CAAC;EACvD,OAAOC,QAAQ,CAACnB,KAAK;AACvB;;AAEA;AACA;AACA;AACA,eAAeoB,YAAYA,CACzBH,SAAiB,EACjBC,OAAiB,EACQ;EACzB,MAAMpB,MAAM,GAAG,MAAMT,UAAU,CAAC+B,YAAY,CAC1CH,SAAS,EACTC,OAAO,IAAIxB,eACb,CAAC;EACD,OAAOG,uBAAuB,CAACC,MAAM,CAAC;AACxC;AAEA,eAAeuB,YAAYA,CACzBJ,SAAiB,EACjBC,OAAiB,EACQ;EACzB,OAAOE,YAAY,CAACH,SAAS,EAAE;IAAE,GAAGN,gBAAgB;IAAE,GAAGO;EAAQ,CAAC,CAAC;AACrE;AAEA,eAAe;EAAEF,IAAI;EAAEI,YAAY;EAAEC;AAAa,CAAC","ignoreList":[]}
@@ -8,22 +8,43 @@ export type NativeOptions = {
8
8
  customWords?: string[];
9
9
  useLanguageCorrection?: boolean;
10
10
  minimumTextHeight?: number;
11
+ includeWords?: boolean;
12
+ regionOfInterest?: NativeBox;
13
+ };
14
+ export type NativeBox = {
15
+ x: number;
16
+ y: number;
17
+ width: number;
18
+ height: number;
19
+ };
20
+ export type NativeWord = {
21
+ text: string;
22
+ box?: NativeBox;
23
+ confidence?: number;
11
24
  };
12
25
  export type NativeTextLine = {
13
26
  text: string;
14
27
  confidence?: number;
28
+ /**
29
+ * @deprecated Sus unidades y su origen difieren entre plataformas (iOS:
30
+ * normalizado x1000 con origen abajo; Android: píxeles con origen arriba),
31
+ * así que no es comparable cross-platform. Usa `box`.
32
+ */
15
33
  frame?: {
16
34
  top: number;
17
35
  left: number;
18
36
  width: number;
19
37
  height: number;
20
38
  };
39
+ box?: NativeBox;
40
+ words?: NativeWord[];
21
41
  recognizedLanguages?: string[];
22
42
  };
23
43
  export type NativeDetailedResult = {
24
44
  fullText: string;
25
45
  lines: string[];
26
46
  details: NativeTextLine[];
47
+ coordinateSpace?: 'normalized-top-left';
27
48
  };
28
49
  export interface Spec extends TurboModule {
29
50
  read(imagePath: string, options?: NativeOptions): Promise<string[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"NativeTextReader.d.ts","sourceRoot":"","sources":["../../../../src/NativeTextReader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,MAAM,aAAa,GAAG;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IACvC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACpE,YAAY,CACV,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAClC;;AAED,wBAA2D"}
1
+ {"version":3,"file":"NativeTextReader.d.ts","sourceRoot":"","sources":["../../../../src/NativeTextReader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,MAAM,aAAa,GAAG;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IACvC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,SAAS,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,KAAK,CAAC,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,qBAAqB,CAAC;CACzC,CAAC;AAEF,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACpE,YAAY,CACV,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAClC;;AAED,wBAA2D"}
@@ -6,22 +6,50 @@ export declare enum ScriptOptions {
6
6
  KOREAN = "Korean"
7
7
  }
8
8
  export type RecognitionLevel = 'fast' | 'accurate';
9
+ /**
10
+ * @deprecated Sus unidades y su origen difieren entre plataformas, así que no
11
+ * es comparable cross-platform. Usa `TextLine.box`.
12
+ */
9
13
  export type TextFrame = {
10
14
  top: number;
11
15
  left: number;
12
16
  width: number;
13
17
  height: number;
14
18
  };
19
+ export type TextBox = {
20
+ x: number;
21
+ y: number;
22
+ width: number;
23
+ height: number;
24
+ };
25
+ export type TextWord = {
26
+ text: string;
27
+ box?: TextBox;
28
+ confidence?: number;
29
+ };
15
30
  export type TextLine = {
16
31
  text: string;
32
+ /**
33
+ * Confianza del motor, 0-1, cuando la expone. `undefined` significa que no
34
+ * hay dato — nunca se rellena con un valor inventado.
35
+ */
17
36
  confidence?: number;
37
+ /** @deprecated Usa `box`. */
18
38
  frame?: TextFrame;
39
+ box?: TextBox;
40
+ /** Palabras de la línea; solo se llena si se pidió `includeWords`. */
41
+ words?: TextWord[];
19
42
  recognizedLanguages?: string[];
20
43
  };
21
44
  export type DetailedResult = {
22
45
  fullText: string;
23
46
  lines: string[];
24
47
  details: TextLine[];
48
+ /**
49
+ * Sistema de coordenadas de las cajas. Ausente en módulos nativos anteriores
50
+ * a la 2.1, donde `box` tampoco existe.
51
+ */
52
+ coordinateSpace?: 'normalized-top-left';
25
53
  };
26
54
  export type Options = {
27
55
  visionIgnoreThreshold?: number;
@@ -32,10 +60,15 @@ export type Options = {
32
60
  customWords?: string[];
33
61
  useLanguageCorrection?: boolean;
34
62
  minimumTextHeight?: number;
63
+ /** Devolver cada palabra con su caja, además de la línea completa. */
64
+ includeWords?: boolean;
65
+ /** Zona a leer, normalizada (0-1) con origen arriba-izquierda. */
66
+ regionOfInterest?: TextBox;
35
67
  };
36
68
  type TextReaderNative = {
37
69
  read(imagePath: string, options?: Options): Promise<string[]>;
38
70
  readDetailed(imagePath: string, options?: Options): Promise<DetailedResult>;
71
+ readDocument(imagePath: string, options?: Options): Promise<DetailedResult>;
39
72
  };
40
73
  declare const _default: TextReaderNative;
41
74
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAsBA,oBAAY,aAAa;IACvB,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,UAAU,eAAe;IACzB,QAAQ,aAAa;IACrB,MAAM,WAAW;CAClB;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,UAAU,CAAC;AAEnD,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,QAAQ,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9D,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC7E,CAAC;wBAyCuC,gBAAgB;AAAzD,wBAA0D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAsBA,oBAAY,aAAa;IACvB,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,UAAU,eAAe;IACzB,QAAQ,aAAa;IACrB,MAAM,WAAW;CAClB;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,UAAU,CAAC;AAEnD;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,sEAAsE;IACtE,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE,qBAAqB,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sEAAsE;IACtE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9D,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC5E,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC7E,CAAC;wBA2DqD,gBAAgB;AAAvE,wBAAwE"}
@@ -8,22 +8,43 @@ export type NativeOptions = {
8
8
  customWords?: string[];
9
9
  useLanguageCorrection?: boolean;
10
10
  minimumTextHeight?: number;
11
+ includeWords?: boolean;
12
+ regionOfInterest?: NativeBox;
13
+ };
14
+ export type NativeBox = {
15
+ x: number;
16
+ y: number;
17
+ width: number;
18
+ height: number;
19
+ };
20
+ export type NativeWord = {
21
+ text: string;
22
+ box?: NativeBox;
23
+ confidence?: number;
11
24
  };
12
25
  export type NativeTextLine = {
13
26
  text: string;
14
27
  confidence?: number;
28
+ /**
29
+ * @deprecated Sus unidades y su origen difieren entre plataformas (iOS:
30
+ * normalizado x1000 con origen abajo; Android: píxeles con origen arriba),
31
+ * así que no es comparable cross-platform. Usa `box`.
32
+ */
15
33
  frame?: {
16
34
  top: number;
17
35
  left: number;
18
36
  width: number;
19
37
  height: number;
20
38
  };
39
+ box?: NativeBox;
40
+ words?: NativeWord[];
21
41
  recognizedLanguages?: string[];
22
42
  };
23
43
  export type NativeDetailedResult = {
24
44
  fullText: string;
25
45
  lines: string[];
26
46
  details: NativeTextLine[];
47
+ coordinateSpace?: 'normalized-top-left';
27
48
  };
28
49
  export interface Spec extends TurboModule {
29
50
  read(imagePath: string, options?: NativeOptions): Promise<string[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"NativeTextReader.d.ts","sourceRoot":"","sources":["../../../../src/NativeTextReader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,MAAM,aAAa,GAAG;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IACvC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B,CAAC;AAEF,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACpE,YAAY,CACV,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAClC;;AAED,wBAA2D"}
1
+ {"version":3,"file":"NativeTextReader.d.ts","sourceRoot":"","sources":["../../../../src/NativeTextReader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,MAAM,aAAa,GAAG;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IACvC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,SAAS,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,KAAK,CAAC,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,qBAAqB,CAAC;CACzC,CAAC;AAEF,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACpE,YAAY,CACV,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAClC;;AAED,wBAA2D"}
@@ -6,22 +6,50 @@ export declare enum ScriptOptions {
6
6
  KOREAN = "Korean"
7
7
  }
8
8
  export type RecognitionLevel = 'fast' | 'accurate';
9
+ /**
10
+ * @deprecated Sus unidades y su origen difieren entre plataformas, así que no
11
+ * es comparable cross-platform. Usa `TextLine.box`.
12
+ */
9
13
  export type TextFrame = {
10
14
  top: number;
11
15
  left: number;
12
16
  width: number;
13
17
  height: number;
14
18
  };
19
+ export type TextBox = {
20
+ x: number;
21
+ y: number;
22
+ width: number;
23
+ height: number;
24
+ };
25
+ export type TextWord = {
26
+ text: string;
27
+ box?: TextBox;
28
+ confidence?: number;
29
+ };
15
30
  export type TextLine = {
16
31
  text: string;
32
+ /**
33
+ * Confianza del motor, 0-1, cuando la expone. `undefined` significa que no
34
+ * hay dato — nunca se rellena con un valor inventado.
35
+ */
17
36
  confidence?: number;
37
+ /** @deprecated Usa `box`. */
18
38
  frame?: TextFrame;
39
+ box?: TextBox;
40
+ /** Palabras de la línea; solo se llena si se pidió `includeWords`. */
41
+ words?: TextWord[];
19
42
  recognizedLanguages?: string[];
20
43
  };
21
44
  export type DetailedResult = {
22
45
  fullText: string;
23
46
  lines: string[];
24
47
  details: TextLine[];
48
+ /**
49
+ * Sistema de coordenadas de las cajas. Ausente en módulos nativos anteriores
50
+ * a la 2.1, donde `box` tampoco existe.
51
+ */
52
+ coordinateSpace?: 'normalized-top-left';
25
53
  };
26
54
  export type Options = {
27
55
  visionIgnoreThreshold?: number;
@@ -32,10 +60,15 @@ export type Options = {
32
60
  customWords?: string[];
33
61
  useLanguageCorrection?: boolean;
34
62
  minimumTextHeight?: number;
63
+ /** Devolver cada palabra con su caja, además de la línea completa. */
64
+ includeWords?: boolean;
65
+ /** Zona a leer, normalizada (0-1) con origen arriba-izquierda. */
66
+ regionOfInterest?: TextBox;
35
67
  };
36
68
  type TextReaderNative = {
37
69
  read(imagePath: string, options?: Options): Promise<string[]>;
38
70
  readDetailed(imagePath: string, options?: Options): Promise<DetailedResult>;
71
+ readDocument(imagePath: string, options?: Options): Promise<DetailedResult>;
39
72
  };
40
73
  declare const _default: TextReaderNative;
41
74
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAsBA,oBAAY,aAAa;IACvB,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,UAAU,eAAe;IACzB,QAAQ,aAAa;IACrB,MAAM,WAAW;CAClB;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,UAAU,CAAC;AAEnD,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,QAAQ,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9D,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC7E,CAAC;wBAyCuC,gBAAgB;AAAzD,wBAA0D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAsBA,oBAAY,aAAa;IACvB,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,UAAU,eAAe;IACzB,QAAQ,aAAa;IACrB,MAAM,WAAW;CAClB;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,UAAU,CAAC;AAEnD;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,sEAAsE;IACtE,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB;;;OAGG;IACH,eAAe,CAAC,EAAE,qBAAqB,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sEAAsE;IACtE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9D,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAC5E,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC7E,CAAC;wBA2DqD,gBAAgB;AAAvE,wBAAwE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-text-reader",
3
- "version": "2.0.1",
3
+ "version": "2.1.1",
4
4
  "description": "A React Native library for OCR using Vision Framework on iOS and ML Kit on Android. Supports Expo development builds, detailed OCR metadata, and Android 16KB page size compatibility.",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/commonjs/index.js",
@@ -10,17 +10,39 @@ export type NativeOptions = {
10
10
  customWords?: string[];
11
11
  useLanguageCorrection?: boolean;
12
12
  minimumTextHeight?: number;
13
+ includeWords?: boolean;
14
+ regionOfInterest?: NativeBox;
15
+ };
16
+
17
+ export type NativeBox = {
18
+ x: number;
19
+ y: number;
20
+ width: number;
21
+ height: number;
22
+ };
23
+
24
+ export type NativeWord = {
25
+ text: string;
26
+ box?: NativeBox;
27
+ confidence?: number;
13
28
  };
14
29
 
15
30
  export type NativeTextLine = {
16
31
  text: string;
17
32
  confidence?: number;
33
+ /**
34
+ * @deprecated Sus unidades y su origen difieren entre plataformas (iOS:
35
+ * normalizado x1000 con origen abajo; Android: píxeles con origen arriba),
36
+ * así que no es comparable cross-platform. Usa `box`.
37
+ */
18
38
  frame?: {
19
39
  top: number;
20
40
  left: number;
21
41
  width: number;
22
42
  height: number;
23
43
  };
44
+ box?: NativeBox;
45
+ words?: NativeWord[];
24
46
  recognizedLanguages?: string[];
25
47
  };
26
48
 
@@ -28,6 +50,7 @@ export type NativeDetailedResult = {
28
50
  fullText: string;
29
51
  lines: string[];
30
52
  details: NativeTextLine[];
53
+ coordinateSpace?: 'normalized-top-left';
31
54
  };
32
55
 
33
56
  export interface Spec extends TurboModule {
package/src/index.tsx CHANGED
@@ -30,6 +30,10 @@ export enum ScriptOptions {
30
30
 
31
31
  export type RecognitionLevel = 'fast' | 'accurate';
32
32
 
33
+ /**
34
+ * @deprecated Sus unidades y su origen difieren entre plataformas, así que no
35
+ * es comparable cross-platform. Usa `TextLine.box`.
36
+ */
33
37
  export type TextFrame = {
34
38
  top: number;
35
39
  left: number;
@@ -37,10 +41,31 @@ export type TextFrame = {
37
41
  height: number;
38
42
  };
39
43
 
44
+ export type TextBox = {
45
+ x: number;
46
+ y: number;
47
+ width: number;
48
+ height: number;
49
+ };
50
+
51
+ export type TextWord = {
52
+ text: string;
53
+ box?: TextBox;
54
+ confidence?: number;
55
+ };
56
+
40
57
  export type TextLine = {
41
58
  text: string;
59
+ /**
60
+ * Confianza del motor, 0-1, cuando la expone. `undefined` significa que no
61
+ * hay dato — nunca se rellena con un valor inventado.
62
+ */
42
63
  confidence?: number;
64
+ /** @deprecated Usa `box`. */
43
65
  frame?: TextFrame;
66
+ box?: TextBox;
67
+ /** Palabras de la línea; solo se llena si se pidió `includeWords`. */
68
+ words?: TextWord[];
44
69
  recognizedLanguages?: string[];
45
70
  };
46
71
 
@@ -48,6 +73,11 @@ export type DetailedResult = {
48
73
  fullText: string;
49
74
  lines: string[];
50
75
  details: TextLine[];
76
+ /**
77
+ * Sistema de coordenadas de las cajas. Ausente en módulos nativos anteriores
78
+ * a la 2.1, donde `box` tampoco existe.
79
+ */
80
+ coordinateSpace?: 'normalized-top-left';
51
81
  };
52
82
 
53
83
  export type Options = {
@@ -59,11 +89,16 @@ export type Options = {
59
89
  customWords?: string[];
60
90
  useLanguageCorrection?: boolean;
61
91
  minimumTextHeight?: number;
92
+ /** Devolver cada palabra con su caja, además de la línea completa. */
93
+ includeWords?: boolean;
94
+ /** Zona a leer, normalizada (0-1) con origen arriba-izquierda. */
95
+ regionOfInterest?: TextBox;
62
96
  };
63
97
 
64
98
  type TextReaderNative = {
65
99
  read(imagePath: string, options?: Options): Promise<string[]>;
66
100
  readDetailed(imagePath: string, options?: Options): Promise<DetailedResult>;
101
+ readDocument(imagePath: string, options?: Options): Promise<DetailedResult>;
67
102
  };
68
103
 
69
104
  const DEFAULT_OPTIONS: Options = {
@@ -74,15 +109,26 @@ function normalizeDetailedResult(result: DetailedResult): DetailedResult {
74
109
  return {
75
110
  fullText: result.fullText ?? '',
76
111
  lines: result.lines ?? [],
112
+ coordinateSpace: result.coordinateSpace,
77
113
  details: (result.details ?? []).map((detail) => ({
78
114
  text: detail.text,
79
115
  confidence: detail.confidence,
80
116
  frame: detail.frame,
117
+ box: detail.box,
118
+ words: detail.words,
81
119
  recognizedLanguages: detail.recognizedLanguages,
82
120
  })),
83
121
  };
84
122
  }
85
123
 
124
+ const DOCUMENT_OPTIONS: Options = {
125
+ script: ScriptOptions.LATIN,
126
+ recognitionLevel: 'accurate',
127
+ useLanguageCorrection: false,
128
+ minimumTextHeight: 0.008,
129
+ includeWords: true,
130
+ };
131
+
86
132
  /**
87
133
  * Extracts text lines from an image.
88
134
  */
@@ -105,4 +151,11 @@ async function readDetailed(
105
151
  return normalizeDetailedResult(result);
106
152
  }
107
153
 
108
- export default { read, readDetailed } as TextReaderNative;
154
+ async function readDocument(
155
+ imagePath: string,
156
+ options?: Options
157
+ ): Promise<DetailedResult> {
158
+ return readDetailed(imagePath, { ...DOCUMENT_OPTIONS, ...options });
159
+ }
160
+
161
+ export default { read, readDetailed, readDocument } as TextReaderNative;