@allmaps/cli
Advanced tools
Comparing version 1.0.0-beta.39 to 1.0.0-beta.40
@@ -5,2 +5,3 @@ import { Command } from 'commander'; | ||
import svg from './annotation/svg.js'; | ||
import imageIds from './annotation/image-ids.js'; | ||
export default function annotation() { | ||
@@ -12,3 +13,4 @@ return new Command('annotation') | ||
.addCommand(generate()) | ||
.addCommand(svg()); | ||
.addCommand(svg()) | ||
.addCommand(imageIds()); | ||
} |
@@ -9,3 +9,3 @@ import { Command } from 'commander'; | ||
.summary('generate Georeference Annotation') | ||
.description(`Generate a single Georeference Annotation from input files`) | ||
.description('Generate a single Georeference Annotation from input files') | ||
.action(async (files) => { | ||
@@ -12,0 +12,0 @@ const jsonValues = await parseJsonInput(files); |
@@ -8,3 +8,3 @@ import { Command } from 'commander'; | ||
.summary('parse Georeference Annotation') | ||
.description(`Parses and validates Georeference Annotations and outputs Allmaps' internal format`) | ||
.description("Parses and validates Georeference Annotations and outputs Allmaps' internal format") | ||
.action(async (files) => { | ||
@@ -11,0 +11,0 @@ const jsonValues = await parseJsonInput(files); |
import { Command } from 'commander'; | ||
import { generateId } from '@allmaps/id'; | ||
import { readFromStdin, printString } from '../lib/io.js'; | ||
// Instead of supplying input files, you can also use the standard input | ||
export default function id() { | ||
@@ -6,0 +5,0 @@ return new Command('id') |
import { Command } from 'commander'; | ||
import parse from './iiif/parse.js'; | ||
import manifest from './iiif/manifest.js'; | ||
import imageIds from './iiif/image-ids.js'; | ||
export default function iiif() { | ||
@@ -9,3 +10,4 @@ return new Command('iiif') | ||
.addCommand(parse()) | ||
.addCommand(manifest()); | ||
.addCommand(manifest()) | ||
.addCommand(imageIds()); | ||
} |
@@ -10,3 +10,3 @@ import { Command } from 'commander'; | ||
.summary('generate IIIF Manifest') | ||
.description(`Generates IIIF Manifest from other IIIF Manifests, IIIF Image Information and Georeference Annotations`) | ||
.description('Generates IIIF Manifest from other IIIF Manifests, IIIF Image Information and Georeference Annotations') | ||
// TODO: add version option to allow choosing between IIIF Presentation API 2.1 and 3.0 | ||
@@ -13,0 +13,0 @@ .option('-i, --id <id>', 'Manifest ID', 'https://example.org/manifest') |
import { Command } from 'commander'; | ||
import { fromZodError } from 'zod-validation-error'; | ||
import { IIIF } from '@allmaps/iiif-parser'; | ||
import { parseJsonInput, printJson } from '../../lib/io.js'; | ||
import { parseIiif } from '../../lib/iiif.js'; | ||
import { addParseIiifOptions } from '../../lib/options.js'; | ||
export default function parse() { | ||
return new Command('parse') | ||
let command = new Command('parse') | ||
.argument('[files...]') | ||
.summary('parse IIIF resources') | ||
.description('Parses IIIF resources and outputs them in the internal format used by Allmaps') | ||
.action(async (files) => { | ||
.description('Parses IIIF resources and outputs them in the internal format used by Allmaps'); | ||
command = addParseIiifOptions(command); | ||
return command.action(async (files, options) => { | ||
const jsonValues = await parseJsonInput(files); | ||
const parsedIiif = []; | ||
const parsedIiifs = []; | ||
for (const jsonValue of jsonValues) { | ||
try { | ||
parsedIiif.push(IIIF.parse(jsonValue)); | ||
const parseIiifOptions = { | ||
fetchCollections: options.fetchCollections, | ||
fetchManifests: options.fetchManifests, | ||
fetchImages: options.fetchImages, | ||
fetchAll: options.fetchAll | ||
}; | ||
const parsedIiif = await parseIiif(jsonValue, parseIiifOptions); | ||
parsedIiifs.push(parsedIiif); | ||
} | ||
@@ -28,8 +37,8 @@ catch (err) { | ||
} | ||
if (parsedIiif.length) { | ||
if (parsedIiifs.length) { | ||
if (jsonValues.length === 1) { | ||
printJson({ ...parsedIiif[0] }); | ||
printJson({ ...parsedIiifs[0] }); | ||
} | ||
else { | ||
printJson({ ...parsedIiif }); | ||
printJson({ ...parsedIiifs }); | ||
} | ||
@@ -36,0 +45,0 @@ } |
@@ -5,2 +5,4 @@ #!/usr/bin/env node | ||
import annotation from './commands/annotation.js'; | ||
import script from './commands/script.js'; | ||
import fetch from './commands/fetch.js'; | ||
import id from './commands/id.js'; | ||
@@ -14,5 +16,7 @@ import iiif from './commands/iiif.js'; | ||
.addCommand(annotation()) | ||
.addCommand(id()) | ||
.addCommand(transform()) | ||
.addCommand(iiif()) | ||
.addCommand(id()) | ||
.addCommand(fetch()) | ||
.addCommand(script()) | ||
.configureHelp({ | ||
@@ -19,0 +23,0 @@ helpWidth: fixedWidth ? 80 : undefined |
@@ -1,29 +0,100 @@ | ||
"use strict"; | ||
// export function gdalwarp (imageFilename, basename, outputDir, gcps, geoMask, tr = 0.5) { | ||
// return ` | ||
// #!/usr/bin/env bash | ||
// mkdir -p ${outputDir} | ||
// gdal_translate -of vrt \\ | ||
// -a_srs EPSG:4326 \\ | ||
// ${gcps.map((gcp) => `-gcp ${gcp.image.join(' ')} ${gcp.world.join(' ')}`).join(' \\\n')} \\ | ||
// ${imageFilename} \\ | ||
// ${outputDir}/${basename}.vrt | ||
// echo '${JSON.stringify(geoMask)}' > ${outputDir}/${basename}.geojson | ||
// gdalwarp -co TILED=YES \\ | ||
// -co COMPRESS=JPEG -co JPEG_QUALITY=80 \\ | ||
// -dstalpha -overwrite \\ | ||
// -cutline ${outputDir}/${basename}.geojson -crop_to_cutline \\ | ||
// -tr ${tr} ${tr} -t_srs "EPSG:3857" \\ | ||
// ${outputDir}/${basename}.vrt \\ | ||
// ${outputDir}/${basename}-warped.tif`.trim() | ||
// } | ||
// export function gdalmerge (outputDir, inputTiffs, outputTiff) { | ||
// // TODO: merge to VRT?!?!?! | ||
// return ` | ||
// gdal_merge.py -o ${outputDir}/${outputTiff} \\ | ||
// ${inputTiffs.map((tiff) => `${outputDir}/${tiff}`).join(' ')}`.trim() | ||
// } | ||
// export function gdal2tiles (outputDir, outputTiff, layerId) { | ||
// return ` | ||
// gdal2tiles.py --xyz ${outputDir}/${outputTiff} ${outputDir}/${layerId}`.trim() | ||
// } | ||
import path from 'path'; | ||
import { checkCommand } from './bash.js'; | ||
const defaultOptions = { | ||
srs: 'EPSG:3857', | ||
quality: 75 | ||
}; | ||
const jqNotFoundMessage = 'Please install jq: https://jqlang.github.io/jq/.'; | ||
const gdalNotFoundMessage = 'Please install GDAL.'; | ||
export function preamble(outputDir) { | ||
return `#!/usr/bin/env bash | ||
mkdir -p ${outputDir} | ||
${checkCommand('gdalinfo', gdalNotFoundMessage)} | ||
${checkCommand('gdalbuildvrt', gdalNotFoundMessage)} | ||
${checkCommand('gdal_translate', gdalNotFoundMessage)} | ||
${checkCommand('gdalwarp', gdalNotFoundMessage)} | ||
${checkCommand('jq', jqNotFoundMessage)}`.trim(); | ||
} | ||
export function checkImageExistsAndCorrectSize(imageFilename, basename, map) { | ||
return ` | ||
if ! [ -f ${imageFilename} ]; then | ||
echo "Image file does not exist: ${imageFilename}" | ||
echo "This script expects a full-size source images for each georeferenced map it processes. See the README for more information." | ||
exit 1 | ||
fi | ||
required_width_${basename}=${map.resource.width} | ||
required_height_${basename}=${map.resource.height} | ||
width_${basename}=( $(gdalinfo -json ${imageFilename} | jq '.size[0]') ) | ||
height_${basename}=( $(gdalinfo -json ${imageFilename} | jq '.size[1]') ) | ||
if [ "$width_${basename}" -eq "$required_width_${basename}" ] && | ||
[ "$height_${basename}" -eq "$required_height_${basename}" ]; then | ||
echo "Found image with correct size: ${imageFilename}" | ||
else | ||
echo "Error: found image with incorrect size" | ||
echo " Image: ${imageFilename}" | ||
echo " Expected: $required_width_${basename} x $required_height_${basename}" | ||
echo " Found: $width_${basename} x $height_${basename}" | ||
exit 1 | ||
fi`.trim(); | ||
} | ||
export function gdalwarp(imageFilename, basename, outputDir, map, geoMask, options) { | ||
// See also: https://blog.cleverelephant.ca/2015/02/geotiff-compression-for-dummies.html | ||
options = { ...defaultOptions, ...options }; | ||
// TODO: parseTransformationType(options, map) | ||
// Read transformation from georeferenced map | ||
// See https://gdal.org/programs/gdalwarp.html#cmdoption-gdalwarp-tps | ||
let transformationArguments = '-order 1'; | ||
let transformationMessage = ''; | ||
if (map.transformation) { | ||
if (map.transformation.type === 'polynomial') { | ||
if (map.transformation.order) { | ||
transformationArguments = `-order ${map.transformation.order}`; | ||
} | ||
} | ||
else if (map.transformation.type === 'thinPlateSpline') { | ||
transformationArguments = '-tps'; | ||
} | ||
else if (map.transformation.type) { | ||
transformationMessage = `Transformation type "${map.transformation.type}" is not supported. Using default transformation.`; | ||
} | ||
} | ||
const vrtFilename = path.join(outputDir, `${basename}.vrt`); | ||
const geojsonFilename = path.join(outputDir, `${basename}.geojson`); | ||
const geotiffFilename = path.join(outputDir, `${basename}-warped.tif`); | ||
return `${transformationMessage ? `echo "${transformationMessage}"` : ''} | ||
gdal_translate -of vrt \\ | ||
-a_srs EPSG:4326 \\ | ||
${map.gcps | ||
.map((gcp) => `-gcp ${gcp.resource.join(' ')} ${gcp.geo.join(' ')}`) | ||
.join(' \\\n')} \\ | ||
${imageFilename} \\ | ||
${vrtFilename} | ||
echo '${JSON.stringify(geoMask)}' > ${geojsonFilename} | ||
gdalwarp \\ | ||
-of COG -co COMPRESS=JPEG -co QUALITY=${options.quality} \\ | ||
-dstalpha -overwrite \\ | ||
-cutline ${geojsonFilename} -crop_to_cutline \\ | ||
-t_srs "${options.srs}" \\ | ||
${transformationArguments} \\ | ||
${vrtFilename} \\ | ||
${geotiffFilename}`.trim(); | ||
} | ||
export function gdalbuildvrt(outputDir, inputTiffs, outputVrt) { | ||
const vrtFilename = path.join(outputDir, outputVrt); | ||
return ` | ||
gdalbuildvrt ${vrtFilename} \\ | ||
${inputTiffs.map((tiff) => path.join(outputDir, tiff)).join(' ')}`.trim(); | ||
} | ||
// TODO: consider adding gdal2tiles export: | ||
// gdal2tiles.py --xyz merged.vrt merged | ||
// TODO: consider adding pmtiles export: | ||
// gdal_translate -of MBTILES merged.vrt merged.mbtiles | ||
// pmtiles convert merged.mbtiles merged.pmtiles |
import type { EmbeddedImage } from '@allmaps/iiif-parser'; | ||
type ParseOptions = { | ||
fetchCollections: boolean; | ||
fetchManifests: boolean; | ||
fetchImages: boolean; | ||
fetchAll: boolean; | ||
}; | ||
export declare function parseIiif(sourceIiif: unknown, options?: Partial<ParseOptions>): Promise<import("@allmaps/iiif-parser").Manifest | import("@allmaps/iiif-parser").Collection | import("@allmaps/iiif-parser").Image>; | ||
export declare function generateManifest(id: string, images: EmbeddedImage[]): { | ||
@@ -34,1 +41,2 @@ '@context': string; | ||
}; | ||
export {}; |
@@ -0,1 +1,35 @@ | ||
import { IIIF } from '@allmaps/iiif-parser'; | ||
const defaultParseOptions = { | ||
fetchCollections: false, | ||
fetchManifests: false, | ||
fetchImages: false, | ||
fetchAll: false | ||
}; | ||
function fetchFn(input, init) { | ||
console.warn('Fetching', input); | ||
return fetch(input, init); | ||
} | ||
export async function parseIiif(sourceIiif, options) { | ||
if (options && options.fetchAll) { | ||
options = { | ||
fetchCollections: true, | ||
fetchManifests: true, | ||
fetchImages: true | ||
}; | ||
} | ||
else { | ||
options = { | ||
...defaultParseOptions, | ||
...options | ||
}; | ||
} | ||
const parsedIiif = IIIF.parse(sourceIiif); | ||
if (parsedIiif.type === 'collection') { | ||
await parsedIiif.fetchAll({ ...options, fetchFn }); | ||
} | ||
else if (parsedIiif.type === 'manifest' && options && options.fetchImages) { | ||
await parsedIiif.fetchAll(fetchFn); | ||
} | ||
return parsedIiif; | ||
} | ||
function generateImageService(image) { | ||
@@ -2,0 +36,0 @@ const profile = image.supportsAnyRegionAndSize ? 'level1' : 'level0'; |
@@ -1,3 +0,3 @@ | ||
/// <reference types="node" /> | ||
import { Readable } from 'stream'; | ||
export declare function readLines(lines: string[]): Promise<string[]>; | ||
export declare function readInput(files: string[]): Promise<string[]>; | ||
@@ -4,0 +4,0 @@ export declare function readFromFiles(files: string[]): string[]; |
@@ -5,2 +5,11 @@ import { createReadStream, readFileSync } from 'fs'; | ||
// Read Input: files (or file) and stdin. For reading general files (svg, strings, ...). | ||
export async function readLines(lines) { | ||
if (process.stdin.isTTY) { | ||
return lines; | ||
} | ||
else { | ||
const stdin = await readFromStdin(); | ||
return stdin.trim().split('\n'); | ||
} | ||
} | ||
export async function readInput(files) { | ||
@@ -7,0 +16,0 @@ if (process.stdin.isTTY) { |
import type { Command } from 'commander'; | ||
export declare function addAnnotationOptions(command: Command): Command; | ||
export declare function addTransformOptions(command: Command): Command; | ||
export declare function addParseIiifOptions(command: Command): Command; |
@@ -24,1 +24,8 @@ const DEFAULT_MAX_OFFSET_RATIO = 0; | ||
} | ||
export function addParseIiifOptions(command) { | ||
return command | ||
.option('-c, --fetch-collections', 'Recursively fetches and parses embedded IIIF Collections', false) | ||
.option('-m, --fetch-manifests', 'Recursively fetches and parses embedded IIIF Manifests', false) | ||
.option('-i, --fetch-images', 'Recursively fetches and parses embedded IIIF Images', false) | ||
.option('-a, --fetch-all', 'Recursively fetches and parses embedded IIIF Collections, Manifests and Images', false); | ||
} |
{ | ||
"name": "@allmaps/cli", | ||
"version": "1.0.0-beta.39", | ||
"version": "1.0.0-beta.40", | ||
"author": { | ||
@@ -54,7 +54,7 @@ "name": "Bert Spaan", | ||
"dependencies": { | ||
"@allmaps/annotation": "^1.0.0-beta.27", | ||
"@allmaps/id": "^1.0.0-beta.27", | ||
"@allmaps/iiif-parser": "^1.0.0-beta.37", | ||
"@allmaps/stdlib": "^1.0.0-beta.28", | ||
"@allmaps/transform": "^1.0.0-beta.38", | ||
"@allmaps/annotation": "^1.0.0-beta.28", | ||
"@allmaps/id": "^1.0.0-beta.28", | ||
"@allmaps/iiif-parser": "^1.0.0-beta.38", | ||
"@allmaps/stdlib": "^1.0.0-beta.29", | ||
"@allmaps/transform": "^1.0.0-beta.39", | ||
"commander": "^10.0.0", | ||
@@ -79,3 +79,3 @@ "stream-json": "^1.7.4", | ||
}, | ||
"gitHead": "2cd1595a894c77557a492e61371508d615d9f6b8" | ||
"gitHead": "ee99d1696cd81fb650cccada4352418ba3e9f2aa" | ||
} |
188
README.md
@@ -9,3 +9,3 @@ # @allmaps/cli | ||
```sh | ||
```bash | ||
npm install -g @allmaps/cli | ||
@@ -16,5 +16,5 @@ ``` | ||
Run Allmaps CLI in your terminal using: | ||
Run Allmaps CLI in your terminal: | ||
```sh | ||
```bash | ||
allmaps | ||
@@ -25,7 +25,7 @@ ``` | ||
```sh | ||
```bash | ||
allmaps --help | ||
``` | ||
```sh | ||
```bash | ||
allmaps <command> --help | ||
@@ -51,3 +51,3 @@ ``` | ||
```sh | ||
```bash | ||
allmaps annotation --help | ||
@@ -58,3 +58,3 @@ ``` | ||
```sh | ||
```bash | ||
allmaps annotation generate [files...] | ||
@@ -65,3 +65,3 @@ ``` | ||
```sh | ||
```bash | ||
allmaps annotation parse [files...] | ||
@@ -72,6 +72,12 @@ ``` | ||
```sh | ||
```bash | ||
allmaps annotation svg [files...] | ||
``` | ||
Output the IDs of the IIIF Images in the input files: | ||
```bash | ||
allmaps annotation image-ids [files...] | ||
``` | ||
For all the commands above, the input files can be either Georeference Annotations or parsed Georeference Annotations | ||
@@ -83,3 +89,3 @@ | ||
```sh | ||
```bash | ||
allmaps transform --help | ||
@@ -104,3 +110,3 @@ ``` | ||
```sh | ||
```bash | ||
allmaps transform svg -a <filename> [files...] | ||
@@ -118,3 +124,3 @@ ``` | ||
```sh | ||
```bash | ||
allmaps transform coordinates -a /path/to/annotation.json /path/to/coordinates.txt | ||
@@ -132,3 +138,3 @@ ``` | ||
```sh | ||
```bash | ||
cat /path/to/coordinates.txt | allmaps transform coordinates -a /path/to/annotation.json \ | ||
@@ -152,3 +158,3 @@ > /path/to/transformed-coordinates.txt | ||
```sh | ||
```bash | ||
allmaps transform coordinates -g /path/to/gcps.txt -t thinPlateSpline /path/to/coordinates.txt | ||
@@ -163,11 +169,11 @@ ``` | ||
```sh | ||
```bash | ||
allmaps transform svg -a <filename> [files...] | ||
``` | ||
```sh | ||
```bash | ||
allmaps transform svg -a /path/to/annotation.json /path/to/svg.svg | ||
``` | ||
```sh | ||
```bash | ||
allmaps transform svg -g /path/to/gcps.txt -t thinPlateSpline /path/to/svg.svg | ||
@@ -182,11 +188,11 @@ ``` | ||
```sh | ||
```bash | ||
allmaps transform geojson -a <filename> [files...] | ||
``` | ||
```sh | ||
```bash | ||
allmaps transform geojson -a /path/to/annotation.json path/to/myGeoJSON.geosjon | ||
``` | ||
```sh | ||
```bash | ||
allmaps transform geojson -g path/to/gcps.txt -t thinPlateSpline /path/to/myGeoJSON.geosjon | ||
@@ -203,7 +209,7 @@ ``` | ||
```sh | ||
```bash | ||
allmaps transform resource-mask [files...] | ||
``` | ||
```sh | ||
```bash | ||
allmaps transform resource-mask path/to/myAnnotation.json path/to/myAnnotation2.json | ||
@@ -234,3 +240,3 @@ ``` | ||
```sh | ||
```bash | ||
allmaps iiif --help | ||
@@ -241,3 +247,3 @@ ``` | ||
```sh | ||
```bash | ||
allmaps iiif parse [files...] | ||
@@ -248,3 +254,3 @@ ``` | ||
```sh | ||
```bash | ||
allmaps manifest -d <id> [files...] | ||
@@ -255,2 +261,8 @@ ``` | ||
Output the IDs of the IIIF Images in the input files: | ||
```bash | ||
allmaps iiif image-ids [files...] | ||
``` | ||
### Generate Allmaps IDs | ||
@@ -262,3 +274,3 @@ | ||
```sh | ||
```bash | ||
allmaps id --help | ||
@@ -269,3 +281,3 @@ ``` | ||
```sh | ||
```bash | ||
allmaps id https://digital.zlb.de/viewer/api/v1/records/34231682/manifest/ | ||
@@ -276,6 +288,112 @@ ``` | ||
```sh | ||
```bash | ||
echo https://digital.zlb.de/viewer/api/v1/records/34231682/manifest/ | allmaps id | ||
``` | ||
### Fetch IIIF images | ||
Fetches the full-size image using a given IIIF Image ID: | ||
```bash | ||
allmaps fetch full-image "https://iiif.digitalcommonwealth.org/iiif/2/commonwealth:7h14cx32p" | ||
``` | ||
> [!NOTE] | ||
> Not all IIIF image servers allow downloading full-sized images. This command does not yet take the image's `maxWidth`, `maxHeight` and `maxArea` properties into account. | ||
### Generate Bash scripts | ||
#### Dezoomify | ||
Generate a Bash script that uses [dezoomify-rs](https://dezoomify-rs.ophir.dev/) to download full-size IIIF images from their IIIF Image IDs: | ||
```bash | ||
allmaps script dezoomify "https://www.davidrumsey.com/luna/servlet/iiif/RUMSEY~8~1~344467~90112435" | ||
``` | ||
You can use dezoomify-rs when the IIIF server does not allow downloading full-size images directly. | ||
#### Create GeoTIFFs using GDAL | ||
Generate a Bash script that uses [GDAL](https://gdal.org/index.html) to convert one or more downloaded full-size IIIF images to [Cloud Optimized GeoTIFFs](https://www.cogeo.org/) using a given Georeference Annotation: | ||
```bash | ||
curl "https://annotations.allmaps.org/images/0b9aef31f14cb5bf" | \ | ||
allmaps script geotiff | ||
``` | ||
> [!NOTE] | ||
> The generated Bash script expects the full-size images to be available on the local file system. You can download these images manually or use the [`allmaps fetch full-image`](#fetch-iiif-images) command. | ||
You can run the generated scripts by saving them to a file: | ||
```bash | ||
curl "https://annotations.allmaps.org/images/0b9aef31f14cb5bf" | \ | ||
allmaps annotation image-ids | \ | ||
allmaps script dezoomify > dezoomify.sh | ||
bash dezoomify.sh | ||
``` | ||
Or by piping them to Bash: | ||
```bash | ||
curl "https://annotations.allmaps.org/images/0b9aef31f14cb5bf" | \ | ||
allmaps annotation image-ids | \ | ||
allmaps script dezoomify | \ | ||
bash | ||
``` | ||
#### Specifying image filenames | ||
By default, the Bash script generated with the `allmaps script geotiff` command computes the Allmaps IDs for all the IIIF Image IDs in the Georeference Annotation and looks for JPGs with the naming convention `<allmaps-id-from-image-id.jpg` in the current directory. | ||
For example, the Georeference Annotation https://annotations.allmaps.org/images/0b9aef31f14cb5bf contains a single georeferenced map from the following IIIF Image: | ||
| IIIF Image ID | Allmaps ID of IIIF Image ID | Expected filename | | ||
| :--------------------------------------------------------------------- | :-------------------------- | :--------------------- | | ||
| `https://iiif-server.lib.uchicago.edu/ark:61001/b2mx3j80nk1f/00000001` | `0b9aef31f14cb5bf` | `0b9aef31f14cb5bf.jpg` | | ||
You can use Allmaps CLI to extract all IIIF Image IDs from a Georeference Annotation: | ||
```bash | ||
curl "https://annotations.allmaps.org/images/0b9aef31f14cb5bf" | \ | ||
allmaps annotation image-ids | ||
``` | ||
This will output: | ||
```bash | ||
https://iiif-server.lib.uchicago.edu/ark:61001/b2mx3j80nk1f/00000001 | ||
``` | ||
The `allmaps id` command generated the Allmaps ID from this IIIF Image ID: | ||
```bash | ||
curl "https://annotations.allmaps.org/images/0b9aef31f14cb5bf" | \ | ||
allmaps annotation image-ids | \ | ||
allmaps id | ||
``` | ||
Output: | ||
```bash | ||
0b9aef31f14cb5bf | ||
``` | ||
You can override the default behavior by supplying a JSON file that maps IIIF Image IDs to local image filenames: | ||
```bash | ||
curl "https://annotations.allmaps.org/images/0b9aef31f14cb5bf" | \ | ||
allmaps script geotiff --image-filenames-file /path/to/image-filenames.json | ||
``` | ||
The file `/path/to/image-filenames.json` should contain a JSON object with IIIF Image IDs as keys and local image filenames as values: | ||
```json | ||
{ | ||
"https://iiif-server.lib.uchicago.edu/ark:61001/b2mx3j80nk1f/00000001": "/path/to/image1.jpg" | ||
} | ||
``` | ||
## Examples | ||
@@ -337,1 +455,15 @@ | ||
``` | ||
### Use GDAL to generate an XYZ tile layer from a Georeference Annotation | ||
```bash | ||
curl "https://annotations.allmaps.org/maps/096f57b5ff35b3eb" | \ | ||
allmaps annotation image-ids | \ | ||
allmaps fetch full-image | ||
curl "https://annotations.allmaps.org/maps/096f57b5ff35b3eb" | \ | ||
allmaps script geotiff | \ | ||
bash | ||
gdal2tiles.py --xyz 096f57b5ff35b3eb.vrt 096f57b5ff35b3eb | ||
``` |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
89110
80
1769
447
4
3