@georeferencing/plugins 0.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/LICENSE +21 -0
- package/README.md +321 -0
- package/dist/data-export.d.ts +9 -0
- package/dist/data-export.js +57 -0
- package/dist/data.d.ts +13 -0
- package/dist/data.js +38 -0
- package/dist/geotiff.d.ts +13 -0
- package/dist/geotiff.js +24 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +9 -0
- package/dist/jpeg.d.ts +13 -0
- package/dist/jpeg.js +33 -0
- package/dist/licenses/APACHE-2.0.txt +202 -0
- package/dist/licenses/GDAL-NOTICE.txt +24 -0
- package/dist/licenses/inventory.json +34 -0
- package/dist/licenses/is-any-array-LICENSE +21 -0
- package/dist/licenses/mgrs-license.md +19 -0
- package/dist/licenses/ml-array-max-LICENSE +21 -0
- package/dist/licenses/ml-array-min-LICENSE +21 -0
- package/dist/licenses/ml-array-rescale-LICENSE +21 -0
- package/dist/licenses/ml-matrix-LICENSE +22 -0
- package/dist/licenses/proj4-LICENSE.md +29 -0
- package/dist/licenses/wkt-parser-LICENSE.md +29 -0
- package/dist/pdf.d.ts +14 -0
- package/dist/pdf.js +23 -0
- package/dist/raster-export.d.ts +4 -0
- package/dist/raster-export.js +58 -0
- package/dist/report.d.ts +80 -0
- package/dist/report.js +224 -0
- package/dist/serializers.d.ts +33 -0
- package/dist/serializers.js +68 -0
- package/dist/tiff.d.ts +45 -0
- package/dist/tiff.js +249 -0
- package/dist/types.d.ts +14 -0
- package/dist/types.js +1 -0
- package/dist/workers/geotiff.d.ts +1 -0
- package/dist/workers/geotiff.js +4 -0
- package/dist/workers/jpeg.d.ts +1 -0
- package/dist/workers/jpeg.js +1 -0
- package/package.json +78 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TobiLG <github@tobilg.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# @georeferencing/plugins
|
|
2
|
+
|
|
3
|
+
Optional local export formats for `@georeferencing/core`: GeoTIFF, JPEG, PDF,
|
|
4
|
+
normalized-image world files, JSON sessions, QGIS control points and accuracy
|
|
5
|
+
reports. Each format is enabled explicitly through controller configuration.
|
|
6
|
+
Heavy implementations load when the user requests an export.
|
|
7
|
+
|
|
8
|
+
This package has no React or OpenLayers dependency. The optional PDF map contract
|
|
9
|
+
is structural and accepts an OpenLayers map. The React editor reads the same
|
|
10
|
+
controller registry to display only configured export actions.
|
|
11
|
+
|
|
12
|
+
## Installation and package selection
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
pnpm add @georeferencing/core @georeferencing/plugins
|
|
16
|
+
# Add the UI only if needed:
|
|
17
|
+
pnpm add @georeferencing/react react@19 react-dom@19 ol@10
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The package ships ESM, TypeScript declarations and codec-worker assets. Node.js
|
|
21
|
+
22.12+ is the declared tooling requirement; repository development uses pnpm 12.x.
|
|
22
|
+
**Install the same version of `@georeferencing/plugins`, `@georeferencing/core`
|
|
23
|
+
and (if used) `@georeferencing/react`**, and upgrade them together. Plugins depend
|
|
24
|
+
on core; a mismatched version can install a second copy of core whose projection
|
|
25
|
+
registry and worker code are separate from the controller's. See
|
|
26
|
+
[keep package versions aligned](https://georeferencing-api-docs.gh.tobilg.com/Getting_started/#keep-package-versions-aligned).
|
|
27
|
+
|
|
28
|
+
Core alone enables no exports. Import only the factories your application uses.
|
|
29
|
+
The root plugin barrel exports factories and types; per-format imports give
|
|
30
|
+
bundlers a narrower dependency graph. Unused formats can be excluded from the
|
|
31
|
+
browser bundle. Installing this package also installs its `pdf-lib` dependency,
|
|
32
|
+
but PDF code is downloaded by the application only when its lazy export path runs.
|
|
33
|
+
|
|
34
|
+
## Pure serializers
|
|
35
|
+
|
|
36
|
+
`@georeferencing/plugins/serializers` exposes `exportPoints(document, definitions?)`,
|
|
37
|
+
`worldFile(fit, workingCrs, outputCrs)` and `accuracyReport(document, fit)` without
|
|
38
|
+
loading a codec worker or UI. These return text/placement values; the `/data`
|
|
39
|
+
factories register full controller exports and downloadable artifacts.
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { importPoints, parseSession } from "@georeferencing/core";
|
|
43
|
+
import { exportPoints, accuracyReport, worldFile } from "@georeferencing/plugins/serializers";
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Session validation and `.points` importing live in core. The `worldFile()`
|
|
47
|
+
factory registered from `@georeferencing/plugins/data` (and the plugin root) is a
|
|
48
|
+
separate controller export format.
|
|
49
|
+
|
|
50
|
+
## Configure export formats
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { GeoreferencerController } from "@georeferencing/core";
|
|
54
|
+
import { createWorkerEngine } from "@georeferencing/core/engine";
|
|
55
|
+
import { geoTiff } from "@georeferencing/plugins/geotiff";
|
|
56
|
+
import { jpeg } from "@georeferencing/plugins/jpeg";
|
|
57
|
+
import { pdf } from "@georeferencing/plugins/pdf";
|
|
58
|
+
|
|
59
|
+
export function createExportEditor(workingCrs: string) {
|
|
60
|
+
const engine = createWorkerEngine();
|
|
61
|
+
const controller = new GeoreferencerController({
|
|
62
|
+
workingCrs,
|
|
63
|
+
engine,
|
|
64
|
+
exports: [
|
|
65
|
+
geoTiff(),
|
|
66
|
+
jpeg({ quality: 0.92, background: [255, 255, 255] }),
|
|
67
|
+
pdf({ paper: "A4", landscape: true, attribution: "Host-provided attribution" }),
|
|
68
|
+
],
|
|
69
|
+
});
|
|
70
|
+
return { controller, engine };
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The caller loads an image and supplies GCPs through the controller or React UI.
|
|
75
|
+
Raster/report exports require a current valid fit. Dispose the controller and
|
|
76
|
+
its host-owned engine when the session is permanently finished.
|
|
77
|
+
|
|
78
|
+
| Factory | Import suffix | Format ID | Files / eligibility |
|
|
79
|
+
| --- | --- | --- | --- |
|
|
80
|
+
| `geoTiff()` | `/geotiff` | `geotiff` | Georeferenced TIFF; valid fit |
|
|
81
|
+
| `jpeg()` | `/jpeg` | `jpeg` | JPEG, `.jgw`, `.crs.json`; valid fit |
|
|
82
|
+
| `pdf()` | `/pdf` | `pdf` | PDF alignment/map report; valid fit and preview |
|
|
83
|
+
| `worldFile()` | `/data` | `world-file` | Original-resolution normalized PNG, `.pgw`, CRS sidecar; Linear/Helmert without reprojection |
|
|
84
|
+
| `session()` | `/data` | `session` | Complete session JSON; fit may be unfinished |
|
|
85
|
+
| `points(definitions?)` | `/data` | `points` | QGIS `.points`; fit may be unfinished |
|
|
86
|
+
| `accuracy()` | `/data` | `accuracy` | Full-precision JSON diagnostics; valid fit |
|
|
87
|
+
|
|
88
|
+
All controller exports currently require loaded source image bytes. Register data
|
|
89
|
+
exports only when needed:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import type { Definitions, GeoreferencerController } from "@georeferencing/core";
|
|
93
|
+
import { accuracy, points, session, worldFile } from "@georeferencing/plugins/data";
|
|
94
|
+
|
|
95
|
+
export function enableDataExports(
|
|
96
|
+
controller: GeoreferencerController,
|
|
97
|
+
definitions: Definitions,
|
|
98
|
+
) {
|
|
99
|
+
controller.setExportFormats([session(), points(definitions), accuracy(), worldFile()]);
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`setExportFormats` replaces the entire registry and cancels pending export work;
|
|
104
|
+
it does not append formats. IDs must be unique. Configuration is runtime state,
|
|
105
|
+
separate from saved session JSON. Removing all formats leaves alignment and host
|
|
106
|
+
feature/draft saving available.
|
|
107
|
+
|
|
108
|
+
## Run an export and consume every artifact
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import type { ExportResult, GeoreferencerController } from "@georeferencing/core";
|
|
112
|
+
|
|
113
|
+
export async function exportSelected(
|
|
114
|
+
controller: GeoreferencerController,
|
|
115
|
+
id: string,
|
|
116
|
+
consume: (result: ExportResult) => Promise<void>,
|
|
117
|
+
) {
|
|
118
|
+
const unavailable = controller.getExportUnavailable(id);
|
|
119
|
+
if (unavailable) throw new Error(unavailable);
|
|
120
|
+
const result = await controller.export(id);
|
|
121
|
+
if (result) await consume(result);
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`ExportResult` contains:
|
|
127
|
+
|
|
128
|
+
| Field | Meaning |
|
|
129
|
+
| --- | --- |
|
|
130
|
+
| `format` | Registered format ID |
|
|
131
|
+
| `document` | Frozen document revision actually processed |
|
|
132
|
+
| `blob` | Primary encoded artifact, also `files[0].blob` |
|
|
133
|
+
| `files` | Suggested filename and Blob for every artifact, including required sidecars |
|
|
134
|
+
| `raster` | Optional full-resolution, pre-encoding RGBA raster, bounds and CRS |
|
|
135
|
+
| `worldFile` | Optional original-pixel placement text and explicit CRS |
|
|
136
|
+
|
|
137
|
+
Save/download each `files` entry with its filename. The React component's
|
|
138
|
+
`onExport(result)` intercepts this same result instead of default downloads.
|
|
139
|
+
Hosts that create object URLs must revoke them after use. A completed export is
|
|
140
|
+
not a persistence acknowledgement and does not clear the dirty flag.
|
|
141
|
+
|
|
142
|
+
Missing formats, invalid eligibility and concurrent exports reject before work
|
|
143
|
+
starts. Lazy-load/processing failures return `null` and populate snapshot errors;
|
|
144
|
+
the operation can be retried. Cancellation and stale work also return `null`.
|
|
145
|
+
Use `cancelExport()` to abort. Image replacement, re-alignment, suspension and
|
|
146
|
+
format-registry changes discard obsolete outputs. Newer drawing edits can remain
|
|
147
|
+
in the draft while the result retains the exact earlier document snapshot.
|
|
148
|
+
|
|
149
|
+
`exportRaster()` is an alias for `export("geotiff")`, and `exportWorldFile()`
|
|
150
|
+
aliases `export("world-file")`. Their matching plugins must be registered.
|
|
151
|
+
|
|
152
|
+
## GeoTIFF output
|
|
153
|
+
|
|
154
|
+
`geoTiff()` uses the core full-resolution warp followed by a dedicated codec
|
|
155
|
+
worker. Configure spatial and creation settings through `controller.setOutput`:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import type { GeoreferencerController } from "@georeferencing/core";
|
|
159
|
+
|
|
160
|
+
export function configureTiff(controller: GeoreferencerController) {
|
|
161
|
+
controller.setOutput({
|
|
162
|
+
...controller.getSnapshot().document.output,
|
|
163
|
+
crs: "EPSG:3857",
|
|
164
|
+
resolution: [2, 2], // two output-CRS units per pixel; choose for your data
|
|
165
|
+
resampler: "bilinear",
|
|
166
|
+
compression: "deflate",
|
|
167
|
+
rowsPerStrip: 256,
|
|
168
|
+
predictor: 2,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
| Setting | Behavior |
|
|
174
|
+
| --- | --- |
|
|
175
|
+
| `crs` | Explicit output CRS; register required definitions with the engine |
|
|
176
|
+
| `bounds` | Optional outer-edge crop extent in output CRS |
|
|
177
|
+
| `resolution` | Positive x/y pixel sizes in output units; omitted means estimated resolution |
|
|
178
|
+
| `resampler` | `nearest`, `bilinear`, `cubic`, `cubicSpline` or `lanczos` |
|
|
179
|
+
| `compression` | `none`, `deflate` or `packbits` |
|
|
180
|
+
| `rowsPerStrip` | Integer 1–4096; default bounded by 256 and raster height |
|
|
181
|
+
| `predictor` | 1 or 2; horizontal predictor 2 requires Deflate |
|
|
182
|
+
| `sourceNoData` | Source byte or RGB triple excluded before interpolation |
|
|
183
|
+
| `noData` | Optional output byte 0–255 with a GDAL no-data tag; otherwise retain alpha |
|
|
184
|
+
|
|
185
|
+
Output is north-up, PixelIsArea, 8-bit RGB or unassociated RGBA. Bounds locate
|
|
186
|
+
outer pixel edges; the first row is at maxY. Numeric no-data cannot preserve
|
|
187
|
+
partial alpha; choose a value that does not collide with valid RGB data. Deflate
|
|
188
|
+
requires browser CompressionStream support.
|
|
189
|
+
|
|
190
|
+
This encoder writes classic TIFF below 4 GiB and requires an EPSG code below
|
|
191
|
+
32767. BigTIFF, COG layout, arbitrary-WKT GeoKeys, scientific sample preservation
|
|
192
|
+
and multipage output are outside the supported envelope. See the
|
|
193
|
+
[capabilities and limits](https://github.com/tobilg/georeferencing/blob/main/packages/documentation/guides/capabilities.md)
|
|
194
|
+
for the supported output envelope and QGIS compatibility boundaries.
|
|
195
|
+
|
|
196
|
+
## JPEG output
|
|
197
|
+
|
|
198
|
+
`jpeg({ quality, background })` shares the same full-resolution warp and output
|
|
199
|
+
grid, then encodes a lossy JPEG. `quality` is 0–1, default 0.92. `background` is an
|
|
200
|
+
RGB byte tuple, default white; transparent pixels are composited onto it.
|
|
201
|
+
TIFF compression and predictor settings do not affect JPEG.
|
|
202
|
+
|
|
203
|
+
JPEG has no embedded CRS. Keep all three files together: the image, `.jgw` world
|
|
204
|
+
file and `.crs.json` metadata. The world file uses the upper-left pixel centre and
|
|
205
|
+
negative y pixel size. JSON records CRS, bounds, dimensions, source identity,
|
|
206
|
+
revision and encoding options. `result.raster` retains the unflattened RGBA warp;
|
|
207
|
+
decoded JPEG pixels can differ because of alpha composition and lossy encoding.
|
|
208
|
+
|
|
209
|
+
## PDF and supplementary exports
|
|
210
|
+
|
|
211
|
+
`pdf()` creates a report from the aligned preview, including GCPs/residuals,
|
|
212
|
+
parameters, source/revision information and an embedded full-precision JSON
|
|
213
|
+
attachment. It is a report, not a geospatial PDF raster export.
|
|
214
|
+
|
|
215
|
+
Options include `paper` (`A4`, `A3`, `Letter`), `landscape`, `margin` in PDF points,
|
|
216
|
+
projection `definitions`, `attribution` and an optional `map` or map accessor.
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
import { pdf, type ReportMap } from "@georeferencing/plugins/pdf";
|
|
220
|
+
|
|
221
|
+
export function mapReport(currentMap: () => ReportMap | undefined) {
|
|
222
|
+
return pdf({ map: currentMap, paper: "A4", margin: 40 });
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
The accessor resolves the current map at export time. Capture uses currently
|
|
227
|
+
loaded canvas layers without moving the view or waiting for pending tiles. Map
|
|
228
|
+
sources must permit CORS canvas export. WebGL-only renderers and arbitrary DOM
|
|
229
|
+
overlays are outside this capture contract. Omit `map` for an aligned-raster-only
|
|
230
|
+
report. PDF cancellation discards a late result but cannot interrupt synchronous
|
|
231
|
+
PDF generation or undo a module download.
|
|
232
|
+
|
|
233
|
+
The `worldFile()` plugin exports orientation-normalized original-resolution PNG
|
|
234
|
+
pixels with matching placement; a world file itself contains no CRS. QGIS
|
|
235
|
+
`.points` exports use the QGIS source-y convention and placeholder residual
|
|
236
|
+
columns; use `accuracy()` for computed diagnostics. A session download preserves
|
|
237
|
+
metadata and features, but not original file bytes, undo history or credentials.
|
|
238
|
+
Neither a downloaded session nor a report counts as a host save.
|
|
239
|
+
|
|
240
|
+
## Worker assets and memory
|
|
241
|
+
|
|
242
|
+
With Vite, use `worker: { format: "es" }`. Default codec URLs resolve relative to
|
|
243
|
+
the installed plugin module, including packed consumers. Each codec can override
|
|
244
|
+
its worker independently:
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
import { geoTiff } from "@georeferencing/plugins/geotiff";
|
|
248
|
+
import { jpeg } from "@georeferencing/plugins/jpeg";
|
|
249
|
+
|
|
250
|
+
export const formats = [
|
|
251
|
+
geoTiff({ workerUrl: "/my-app/assets/geotiff.js" }),
|
|
252
|
+
jpeg({ workerUrl: "/my-app/assets/jpeg.js", quality: 0.9 }),
|
|
253
|
+
];
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Copy the matching `dist/workers/geotiff.js` or `jpeg.js`, adjacent legal notices
|
|
257
|
+
and `dist/licenses` when deploying assets yourself. Alternatively supply a
|
|
258
|
+
`workerFactory` returning a fresh dedicated module worker. Vite supports asset
|
|
259
|
+
imports from `@georeferencing/plugins/geotiff-worker?worker` and
|
|
260
|
+
`@georeferencing/plugins/jpeg-worker?worker`. Respect the deployment base and CSP.
|
|
261
|
+
|
|
262
|
+
Raster codecs inherit engine limits, projection definitions, scheduling and
|
|
263
|
+
cancellation. Temporary raster buffers transfer to the encoder and back; the
|
|
264
|
+
editor preview is never transferred. Low-level callers must treat submitted
|
|
265
|
+
buffers as detached until the returned raster arrives. Aborting terminates a
|
|
266
|
+
codec worker. Core defaults are 24MP input/output and 768 MiB estimated reservation;
|
|
267
|
+
compression and buffers may require a smaller practical output. These estimates
|
|
268
|
+
are not measured process-memory caps or streaming guarantees.
|
|
269
|
+
|
|
270
|
+
## Custom exporters and low-level APIs
|
|
271
|
+
|
|
272
|
+
A custom descriptor implements core's `ExportFormat` contract; it does not need
|
|
273
|
+
to depend on this package. Respect the supplied AbortSignal and frozen document.
|
|
274
|
+
The first file's Blob must be the primary returned Blob.
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
import type { ExportFormat } from "@georeferencing/core";
|
|
278
|
+
|
|
279
|
+
export const provenance: ExportFormat = {
|
|
280
|
+
id: "provenance",
|
|
281
|
+
label: "Export provenance",
|
|
282
|
+
requiresFit: false,
|
|
283
|
+
load: async () => ({
|
|
284
|
+
async run({ document, signal }) {
|
|
285
|
+
signal.throwIfAborted();
|
|
286
|
+
const blob = new Blob([JSON.stringify({
|
|
287
|
+
documentId: document.id,
|
|
288
|
+
revision: document.documentRevision,
|
|
289
|
+
source: document.sourceImage,
|
|
290
|
+
})], { type: "application/json" });
|
|
291
|
+
return { blob, files: [{ name: "provenance.json", blob }] };
|
|
292
|
+
},
|
|
293
|
+
}),
|
|
294
|
+
};
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
For a larger implementation, have `load` dynamically import your own module.
|
|
298
|
+
Use `raster: true` to request shared raster output controls, and `unavailable` for
|
|
299
|
+
additional pure eligibility checks. All exporters share the controller's revision
|
|
300
|
+
and cancellation contract.
|
|
301
|
+
|
|
302
|
+
`@georeferencing/plugins/tiff` exposes low-level TIFF encoders and option
|
|
303
|
+
validation. `/report` exposes `createPdfReport`, `captureMap` and structural map
|
|
304
|
+
interfaces. Bypassing the controller makes the caller responsible for matching
|
|
305
|
+
revisions, limits, cancellation and resource cleanup. Custom codec workers can
|
|
306
|
+
use `installEncoderWorker` from `@georeferencing/core/encoder-worker`.
|
|
307
|
+
|
|
308
|
+
## Troubleshooting and license
|
|
309
|
+
|
|
310
|
+
| Symptom | Check |
|
|
311
|
+
| --- | --- |
|
|
312
|
+
| No export buttons / `EXPORT_DISABLED` | Register the intended format on the controller |
|
|
313
|
+
| Lazy module or codec load fails | Bundler output, asset base URL and CSP; retry after correcting deployment |
|
|
314
|
+
| JPEG appears unreferenced in another app | Keep both sidecars and configure/read the recorded CRS |
|
|
315
|
+
| PDF cannot capture a map | Loaded canvas layers, visible map size and CORS; omit optional map capture if unsupported |
|
|
316
|
+
| TIFF option or memory error | Compatible compression/predictor/no-data settings and output size |
|
|
317
|
+
|
|
318
|
+
MIT licensed, with bundled third-party notices in `dist/licenses`. Public TypeDoc
|
|
319
|
+
comments ship in declarations and are published as the
|
|
320
|
+
[API documentation](https://georeferencing-api-docs.gh.tobilg.com). Source, issues and contribution notes are in the
|
|
321
|
+
[GitHub repository](https://github.com/tobilg/georeferencing).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Definitions, Exporter } from "@georeferencing/core";
|
|
2
|
+
/** @internal */
|
|
3
|
+
export declare const sessionExporter: Exporter;
|
|
4
|
+
/** @internal */
|
|
5
|
+
export declare function pointsExporter(definitions: Definitions): Exporter;
|
|
6
|
+
/** @internal */
|
|
7
|
+
export declare const accuracyExporter: Exporter;
|
|
8
|
+
/** @internal */
|
|
9
|
+
export declare const worldFileExporter: Exporter;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { accuracyReport, exportPoints, worldFile } from "./serializers.js";
|
|
2
|
+
const textFile = (name, text, type = "application/json") => ({
|
|
3
|
+
name,
|
|
4
|
+
blob: new Blob([text], { type }),
|
|
5
|
+
});
|
|
6
|
+
/** @internal */
|
|
7
|
+
export const sessionExporter = {
|
|
8
|
+
async run({ document }) {
|
|
9
|
+
const file = textFile("session.json", JSON.stringify(document, null, 2));
|
|
10
|
+
return { blob: file.blob, files: [file] };
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
/** @internal */
|
|
14
|
+
export function pointsExporter(definitions) {
|
|
15
|
+
return {
|
|
16
|
+
async run({ document }) {
|
|
17
|
+
const file = textFile("image.points", exportPoints(document, definitions), "text/plain");
|
|
18
|
+
return { blob: file.blob, files: [file] };
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/** @internal */
|
|
23
|
+
export const accuracyExporter = {
|
|
24
|
+
async run({ document, fit }) {
|
|
25
|
+
if (!fit)
|
|
26
|
+
throw Error("A valid alignment is required.");
|
|
27
|
+
const file = textFile("accuracy-report.json", accuracyReport(document, fit));
|
|
28
|
+
return { blob: file.blob, files: [file] };
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
/** @internal */
|
|
32
|
+
export const worldFileExporter = {
|
|
33
|
+
async run({ document, fit, file, engine, tag, signal, onProgress }) {
|
|
34
|
+
if (!fit || !file || !document.sourceImage)
|
|
35
|
+
throw Error("A matching image and fit are required.");
|
|
36
|
+
const placement = worldFile(fit, document.workingCrs, document.output.crs);
|
|
37
|
+
const result = await engine.run({ kind: "normalize", file, metadata: document.sourceImage }, tag, { signal, onProgress });
|
|
38
|
+
signal.throwIfAborted();
|
|
39
|
+
if (!result.blob)
|
|
40
|
+
throw Error("Image normalization did not return PNG bytes.");
|
|
41
|
+
return {
|
|
42
|
+
blob: result.blob,
|
|
43
|
+
worldFile: placement,
|
|
44
|
+
files: [
|
|
45
|
+
{ name: "image.png", blob: result.blob },
|
|
46
|
+
textFile("image.pgw", placement.text, "text/plain"),
|
|
47
|
+
textFile("image.crs.json", JSON.stringify({
|
|
48
|
+
crs: placement.crs,
|
|
49
|
+
image: document.sourceImage,
|
|
50
|
+
documentId: document.id,
|
|
51
|
+
revision: document.documentRevision,
|
|
52
|
+
note: "Applies to the accompanying orientation-normalized original-resolution image.png",
|
|
53
|
+
}, null, 2)),
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
};
|
package/dist/data.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional session, QGIS points, world-file and accuracy exports.
|
|
3
|
+
* @module data
|
|
4
|
+
*/
|
|
5
|
+
import type { Definitions, ExportFormat } from "@georeferencing/core";
|
|
6
|
+
/** Register a complete version-1 JSON session download, even before a valid fit. */
|
|
7
|
+
export declare function session(): ExportFormat;
|
|
8
|
+
/** Register QGIS .points download, projecting targets with the supplied definitions. */
|
|
9
|
+
export declare function points(definitions?: Definitions): ExportFormat;
|
|
10
|
+
/** Register a full-precision JSON alignment report with training residual formulas. */
|
|
11
|
+
export declare function accuracy(): ExportFormat;
|
|
12
|
+
/** Register original-resolution normalized PNG, world file and explicit CRS sidecar. */
|
|
13
|
+
export declare function worldFile(): ExportFormat;
|
package/dist/data.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Register a complete version-1 JSON session download, even before a valid fit. */
|
|
2
|
+
export function session() {
|
|
3
|
+
return {
|
|
4
|
+
id: "session",
|
|
5
|
+
label: "Export session",
|
|
6
|
+
requiresFit: false,
|
|
7
|
+
load: async () => (await import("./data-export.js")).sessionExporter,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/** Register QGIS .points download, projecting targets with the supplied definitions. */
|
|
11
|
+
export function points(definitions = {}) {
|
|
12
|
+
return {
|
|
13
|
+
id: "points",
|
|
14
|
+
label: "Export .points",
|
|
15
|
+
requiresFit: false,
|
|
16
|
+
load: async () => (await import("./data-export.js")).pointsExporter(definitions),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/** Register a full-precision JSON alignment report with training residual formulas. */
|
|
20
|
+
export function accuracy() {
|
|
21
|
+
return {
|
|
22
|
+
id: "accuracy",
|
|
23
|
+
label: "Accuracy report",
|
|
24
|
+
load: async () => (await import("./data-export.js")).accuracyExporter,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Register original-resolution normalized PNG, world file and explicit CRS sidecar. */
|
|
28
|
+
export function worldFile() {
|
|
29
|
+
return {
|
|
30
|
+
id: "world-file",
|
|
31
|
+
label: "World file & CRS",
|
|
32
|
+
unavailable: (doc) => ["linear", "helmert"].includes(doc.model) &&
|
|
33
|
+
doc.workingCrs === doc.output.crs
|
|
34
|
+
? null
|
|
35
|
+
: "World-file output requires Linear/Helmert without reprojection.",
|
|
36
|
+
load: async () => (await import("./data-export.js")).worldFileExporter,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional GeoTIFF export; import from `@georeferencing/plugins/geotiff`.
|
|
3
|
+
* @module geotiff
|
|
4
|
+
*/
|
|
5
|
+
import type { ExportFormat } from "@georeferencing/core";
|
|
6
|
+
import type { RasterPluginOptions } from "./types.js";
|
|
7
|
+
export type { RasterPluginOptions } from "./types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Register lazy GeoTIFF export. Encoding runs in a dedicated plugin worker using
|
|
10
|
+
* the controller engine's limits, projections, scheduler and cancellation.
|
|
11
|
+
* No workers or heavy encoder code load until the user requests this format.
|
|
12
|
+
*/
|
|
13
|
+
export declare function geoTiff(options?: RasterPluginOptions): ExportFormat;
|
package/dist/geotiff.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Register lazy GeoTIFF export. Encoding runs in a dedicated plugin worker using
|
|
3
|
+
* the controller engine's limits, projections, scheduler and cancellation.
|
|
4
|
+
* No workers or heavy encoder code load until the user requests this format.
|
|
5
|
+
*/
|
|
6
|
+
export function geoTiff(options = {}) {
|
|
7
|
+
return {
|
|
8
|
+
id: "geotiff",
|
|
9
|
+
label: "Export GeoTIFF",
|
|
10
|
+
raster: true,
|
|
11
|
+
load: async () => {
|
|
12
|
+
const { renderAndEncode } = await import("./raster-export.js");
|
|
13
|
+
return {
|
|
14
|
+
run: (context) => renderAndEncode(context, "geotiff", {
|
|
15
|
+
...options,
|
|
16
|
+
workerFactory: options.workerFactory ??
|
|
17
|
+
(options.workerUrl
|
|
18
|
+
? undefined
|
|
19
|
+
: () => new Worker(new URL("./workers/geotiff.js", import.meta.url), { type: "module" })),
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional lazy export formats. Prefer per-format imports to give bundlers the
|
|
3
|
+
* narrowest dependency graph. Register descriptors with ControllerOptions.exports.
|
|
4
|
+
* @module plugins
|
|
5
|
+
*/
|
|
6
|
+
export { accuracy, points, session, worldFile } from "./data.js";
|
|
7
|
+
export { geoTiff } from "./geotiff.js";
|
|
8
|
+
export { jpeg } from "./jpeg.js";
|
|
9
|
+
export type { PdfOptions, ReportMap, ReportOptions, ReportView, } from "./pdf.js";
|
|
10
|
+
export { pdf } from "./pdf.js";
|
|
11
|
+
export type { JpegOptions, RasterPluginOptions } from "./types.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional lazy export formats. Prefer per-format imports to give bundlers the
|
|
3
|
+
* narrowest dependency graph. Register descriptors with ControllerOptions.exports.
|
|
4
|
+
* @module plugins
|
|
5
|
+
*/
|
|
6
|
+
export { accuracy, points, session, worldFile } from "./data.js";
|
|
7
|
+
export { geoTiff } from "./geotiff.js";
|
|
8
|
+
export { jpeg } from "./jpeg.js";
|
|
9
|
+
export { pdf } from "./pdf.js";
|
package/dist/jpeg.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional georeferenced JPEG export; import from `@georeferencing/plugins/jpeg`.
|
|
3
|
+
* @module jpeg
|
|
4
|
+
*/
|
|
5
|
+
import type { ExportFormat } from "@georeferencing/core";
|
|
6
|
+
import type { JpegOptions } from "./types.js";
|
|
7
|
+
export type { JpegOptions } from "./types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Register lazy JPEG export with a pixel-centre world file and explicit CRS/source
|
|
10
|
+
* JSON sidecar. Transparency is composited over the configured background.
|
|
11
|
+
* @throws GeoreferenceError For an invalid quality or RGB background.
|
|
12
|
+
*/
|
|
13
|
+
export declare function jpeg(options?: JpegOptions): ExportFormat;
|
package/dist/jpeg.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { GeoreferenceError } from "@georeferencing/core";
|
|
2
|
+
/**
|
|
3
|
+
* Register lazy JPEG export with a pixel-centre world file and explicit CRS/source
|
|
4
|
+
* JSON sidecar. Transparency is composited over the configured background.
|
|
5
|
+
* @throws GeoreferenceError For an invalid quality or RGB background.
|
|
6
|
+
*/
|
|
7
|
+
export function jpeg(options = {}) {
|
|
8
|
+
const quality = options.quality ?? 0.92;
|
|
9
|
+
const background = options.background ?? [255, 255, 255];
|
|
10
|
+
if (!Number.isFinite(quality) ||
|
|
11
|
+
quality < 0 ||
|
|
12
|
+
quality > 1 ||
|
|
13
|
+
background.length !== 3 ||
|
|
14
|
+
background.some((v) => !Number.isInteger(v) || v < 0 || v > 255))
|
|
15
|
+
throw new GeoreferenceError("JPEG_OPTIONS", "JPEG quality must be 0–1 and background must contain three RGB bytes.");
|
|
16
|
+
return {
|
|
17
|
+
id: "jpeg",
|
|
18
|
+
label: "Export JPEG",
|
|
19
|
+
raster: true,
|
|
20
|
+
load: async () => {
|
|
21
|
+
const { renderAndEncode } = await import("./raster-export.js");
|
|
22
|
+
return {
|
|
23
|
+
run: (context) => renderAndEncode(context, "jpeg", {
|
|
24
|
+
...options,
|
|
25
|
+
workerFactory: options.workerFactory ??
|
|
26
|
+
(options.workerUrl
|
|
27
|
+
? undefined
|
|
28
|
+
: () => new Worker(new URL("./workers/jpeg.js", import.meta.url), { type: "module" })),
|
|
29
|
+
}, { quality, background: [...background] }),
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|