react-native-text-reader 2.0.1 → 2.1.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.
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()
57
+
58
+ return image ?: throw IOException("Failed to decode remote image.")
59
+ }
62
60
 
63
- InputImage.fromBitmap(image, 0)
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,6 +168,20 @@ class TextReaderModule(reactContext: ReactApplicationContext) :
125
168
  })
126
169
  }
127
170
  putArray("elements", elementsArray)
171
+
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)
184
+ }
128
185
  }
129
186
  }
130
187
 
@@ -157,7 +214,7 @@ class TextReaderModule(reactContext: ReactApplicationContext) :
157
214
  private fun sortedLines(visionText: Text, confidenceThreshold: Float): List<Text.Line> {
158
215
  return visionText.textBlocks
159
216
  .flatMap { block -> block.lines }
160
- .filter { line -> lineConfidence(line) >= confidenceThreshold }
217
+ .filter { line -> (lineConfidence(line) ?: Float.MAX_VALUE) >= confidenceThreshold }
161
218
  .sortedWith(compareBy({ it.boundingBox?.top ?: 0 }, { it.boundingBox?.left ?: 0 }))
162
219
  }
163
220
 
@@ -179,15 +236,36 @@ class TextReaderModule(reactContext: ReactApplicationContext) :
179
236
  0.0f
180
237
  }
181
238
 
239
+ val includeWords = options?.hasKey("includeWords") == true &&
240
+ options.getBoolean("includeWords")
241
+
182
242
  val recognizer: TextRecognizer = TextRecognition.getClient(getScriptTextRecognizerOptions(script))
183
243
 
184
244
  try {
185
- val image = getInputImage(reactApplicationContext, url)
245
+ val region = if (options?.hasKey("regionOfInterest") == true) {
246
+ options.getMap("regionOfInterest")
247
+ } else {
248
+ null
249
+ }
250
+ val image = if (region != null) {
251
+ croppedInputImage(reactApplicationContext, url, region)
252
+ } else {
253
+ getInputImage(reactApplicationContext, url)
254
+ }
255
+
186
256
  recognizer.process(image)
187
257
  .addOnSuccessListener { visionText ->
188
258
  val lines = sortedLines(visionText, confidenceThreshold)
189
259
  if (detailed) {
190
- promise.resolve(buildDetailedResult(visionText, lines))
260
+ promise.resolve(
261
+ buildDetailedResult(
262
+ visionText,
263
+ lines,
264
+ image.width,
265
+ image.height,
266
+ includeWords
267
+ )
268
+ )
191
269
  } else {
192
270
  val linesArray = Arguments.createArray()
193
271
  lines.forEach { line -> linesArray.pushString(line.text) }
@@ -209,11 +287,17 @@ class TextReaderModule(reactContext: ReactApplicationContext) :
209
287
  }
210
288
  }
211
289
 
212
- private fun buildDetailedResult(visionText: Text, lines: List<Text.Line>): WritableMap {
290
+ private fun buildDetailedResult(
291
+ visionText: Text,
292
+ lines: List<Text.Line>,
293
+ imageWidth: Int,
294
+ imageHeight: Int,
295
+ includeWords: Boolean
296
+ ): WritableMap {
213
297
  val lineTexts = lines.map { it.text }
214
298
  val detailsArray = Arguments.createArray()
215
299
  lines.forEach { line ->
216
- detailsArray.pushMap(lineToMap(line))
300
+ detailsArray.pushMap(lineToMap(line, imageWidth, imageHeight, includeWords))
217
301
  }
218
302
 
219
303
  return Arguments.createMap().apply {
@@ -222,6 +306,7 @@ class TextReaderModule(reactContext: ReactApplicationContext) :
222
306
  lineTexts.forEach { pushString(it) }
223
307
  })
224
308
  putArray("details", detailsArray)
309
+ putString("coordinateSpace", "normalized-top-left")
225
310
  }
226
311
  }
227
312
 
@@ -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.0",
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;