Gabriel commited on
Commit
ac831e9
·
verified ·
1 Parent(s): a2aebe8

Create docs.md

Browse files
Files changed (1) hide show
  1. docs.md +773 -0
docs.md ADDED
@@ -0,0 +1,773 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # IIIF APIs Reference (Image API 3.0 & Presentation API 3.0)
2
+
3
+ ## Overview
4
+
5
+ The IIIF (International Image Interoperability Framework) consists of complementary APIs for delivering and presenting digital content:
6
+
7
+ - **Image API**: Web service for image manipulation and delivery via URI parameters
8
+ - **Presentation API**: JSON-LD format for describing structure, metadata, and presentation of compound digital objects
9
+ - **Content Search API**: Full-text search within IIIF resources
10
+
11
+ ## IIIF Image API 3.0
12
+
13
+ ## URI Syntax
14
+
15
+ ### Base URI Template
16
+ ```
17
+ {scheme}://{server}{/prefix}/{identifier}
18
+ ```
19
+
20
+ ### Image Request URI Template
21
+ ```
22
+ {scheme}://{server}{/prefix}/{identifier}/{region}/{size}/{rotation}/{quality}.{format}
23
+ ```
24
+
25
+ ### Image Information Request URI Template
26
+ ```
27
+ {scheme}://{server}{/prefix}/{identifier}/info.json
28
+ ```
29
+
30
+ ## URI Components
31
+
32
+ | Component | Description |
33
+ |-----------|-------------|
34
+ | scheme | HTTP or HTTPS protocol |
35
+ | server | Host server (may include port number) |
36
+ | prefix | Optional path to the service on the host server |
37
+ | identifier | Identifier of the requested image (ARK, URN, filename, etc.) |
38
+
39
+ **Important**: Special characters in identifiers MUST be URI encoded, including slashes (/).
40
+
41
+ ## Image Request Parameters
42
+
43
+ Parameters must be specified in this exact order: region/size/rotation/quality.format
44
+
45
+ ### Region Parameter
46
+
47
+ Defines the rectangular portion of the image to return.
48
+
49
+ | Form | Description | Example |
50
+ |------|-------------|---------|
51
+ | `full` | Return the complete image | `full` |
52
+ | `square` | Return square region (shorter dimension) | `square` |
53
+ | `x,y,w,h` | Pixel coordinates (x,y) and dimensions (w,h) | `125,15,120,140` |
54
+ | `pct:x,y,w,h` | Percentage coordinates and dimensions | `pct:41.6,7.5,40,70` |
55
+
56
+ ### Size Parameter
57
+
58
+ Specifies dimensions for scaling the extracted region.
59
+
60
+ | Form | Description | Example |
61
+ |------|-------------|---------|
62
+ | `max` | Maximum size available (no upscaling) | `max` |
63
+ | `^max` | Maximum size (allows upscaling) | `^max` |
64
+ | `w,` | Scale to exact width | `150,` |
65
+ | `^w,` | Scale to exact width (allows upscaling) | `^200,` |
66
+ | `,h` | Scale to exact height | `,100` |
67
+ | `^,h` | Scale to exact height (allows upscaling) | `^,150` |
68
+ | `pct:n` | Scale to n percent (max 100%) | `pct:50` |
69
+ | `^pct:n` | Scale to n percent (allows upscaling) | `^pct:150` |
70
+ | `w,h` | Exact width and height (may distort) | `200,300` |
71
+ | `^w,h` | Exact width and height (allows upscaling) | `^250,400` |
72
+ | `!w,h` | Best fit within w,h (maintains aspect ratio) | `!200,300` |
73
+
74
+ ### Rotation Parameter
75
+
76
+ Specifies mirroring and rotation to be applied to the image.
77
+
78
+ | Form | Description |
79
+ |------|-------------|
80
+ | `0` | No rotation |
81
+ | `90`, `180`, `270` | Clockwise rotation in degrees |
82
+ | `!0`, `!90`, etc. | Horizontal mirroring then rotation |
83
+
84
+ ### Quality Parameter
85
+
86
+ Determines color characteristics of the image.
87
+
88
+ | Value | Description |
89
+ |-------|-------------|
90
+ | `default` | Server-determined default quality |
91
+ | `color` | Full color image |
92
+ | `gray` | Grayscale image |
93
+ | `bitonal` | Black and white image |
94
+
95
+ ### Format Parameter
96
+
97
+ Specifies the output format.
98
+
99
+ Common formats: `jpg`, `png`, `gif`, `webp`, `tif`
100
+
101
+ ---
102
+
103
+ ## IIIF Presentation API 3.0
104
+
105
+ ### Purpose
106
+ The Presentation API provides a standardized way to describe compound digital objects (books, manuscripts, albums, etc.) with their structure, metadata, and presentation instructions. It uses JSON-LD format to enable rich viewing experiences across different client applications.
107
+
108
+ ### Core Resource Types
109
+
110
+ #### Collection
111
+ Ordered list of Manifests and/or other Collections for hierarchical organization.
112
+ ```json
113
+ {
114
+ "@context": "http://iiif.io/api/presentation/3/context.json",
115
+ "id": "https://example.org/collection/books",
116
+ "type": "Collection",
117
+ "label": { "en": ["Book Collection"] },
118
+ "items": [
119
+ {
120
+ "id": "https://example.org/manifest/book1",
121
+ "type": "Manifest",
122
+ "label": { "en": ["Book 1"] }
123
+ }
124
+ ]
125
+ }
126
+ ```
127
+
128
+ #### Manifest
129
+ Describes a single compound object with its structure, metadata, and viewing instructions.
130
+ ```json
131
+ {
132
+ "@context": "http://iiif.io/api/presentation/3/context.json",
133
+ "id": "https://example.org/manifest/book1",
134
+ "type": "Manifest",
135
+ "label": { "en": ["Example Book"] },
136
+ "summary": { "en": ["A description of this book"] },
137
+ "metadata": [
138
+ {
139
+ "label": { "en": ["Author"] },
140
+ "value": { "en": ["Jane Doe"] }
141
+ }
142
+ ],
143
+ "items": [
144
+ {
145
+ "id": "https://example.org/canvas/page1",
146
+ "type": "Canvas",
147
+ "label": { "en": ["Page 1"] },
148
+ "height": 1000,
149
+ "width": 750,
150
+ "items": [
151
+ {
152
+ "id": "https://example.org/page/page1/annopage",
153
+ "type": "AnnotationPage",
154
+ "items": [
155
+ {
156
+ "id": "https://example.org/page/page1/anno",
157
+ "type": "Annotation",
158
+ "motivation": "painting",
159
+ "body": {
160
+ "id": "https://example.org/iiif/page1/full/max/0/default.jpg",
161
+ "type": "Image",
162
+ "format": "image/jpeg",
163
+ "service": [
164
+ {
165
+ "id": "https://example.org/iiif/page1",
166
+ "type": "ImageService3",
167
+ "profile": "level2"
168
+ }
169
+ ]
170
+ },
171
+ "target": "https://example.org/canvas/page1"
172
+ }
173
+ ]
174
+ }
175
+ ]
176
+ }
177
+ ]
178
+ }
179
+ ```
180
+
181
+ #### Canvas
182
+ Virtual container representing a view of the object (page, image, time segment) with defined dimensions.
183
+ - **Spatial**: Uses `height` and `width` properties
184
+ - **Temporal**: Uses `duration` property
185
+ - **Mixed**: Can have all three dimensions
186
+
187
+ #### Range
188
+ Defines structural sections within an object (chapters, movements, articles).
189
+ ```json
190
+ {
191
+ "id": "https://example.org/range/chapter1",
192
+ "type": "Range",
193
+ "label": { "en": ["Chapter 1"] },
194
+ "items": [
195
+ { "id": "https://example.org/canvas/page1", "type": "Canvas" },
196
+ { "id": "https://example.org/canvas/page2", "type": "Canvas" }
197
+ ]
198
+ }
199
+ ```
200
+
201
+ #### Annotation & Annotation Page
202
+ Content is associated with Canvases through Annotations collected in Annotation Pages.
203
+ - **Painting motivation**: Content that is part of the Canvas (images, video, audio)
204
+ - **Supplementing motivation**: Content derived from the Canvas (transcriptions, translations)
205
+ - **Other motivations**: Commentary, tags, etc.
206
+
207
+ ### Essential Properties
208
+
209
+ #### Required Properties
210
+ - **id**: HTTP(S) URI identifier
211
+ - **type**: Resource class (Collection, Manifest, Canvas, etc.)
212
+ - **label**: Human-readable name (internationalized)
213
+
214
+ #### Key Descriptive Properties
215
+ - **metadata**: Array of label/value pairs for display
216
+ - **summary**: Brief description
217
+ - **thumbnail**: Representative image(s)
218
+ - **provider**: Institution/organization information
219
+ - **rights**: License or rights statement URI
220
+ - **requiredStatement**: Text that must be displayed (attribution)
221
+
222
+ #### Technical Properties
223
+ - **height/width**: Pixel dimensions for images, aspect ratio for Canvas
224
+ - **duration**: Time length in seconds
225
+ - **format**: MIME type (e.g., "image/jpeg")
226
+ - **profile**: Schema or functionality description
227
+ - **viewingDirection**: Display order (left-to-right, right-to-left, etc.)
228
+ - **behavior**: Presentation hints (paged, continuous, individuals, etc.)
229
+
230
+ #### Structural Properties
231
+ - **items**: Ordered list of child resources
232
+ - **structures**: Top-level Ranges for table of contents
233
+ - **annotations**: Commentary Annotation Pages
234
+
235
+ ### Language Internationalization
236
+ Properties like `label`, `summary`, and `metadata` use language maps:
237
+ ```json
238
+ {
239
+ "label": {
240
+ "en": ["English Title"],
241
+ "fr": ["Titre Français"],
242
+ "none": ["No Language"]
243
+ }
244
+ }
245
+ ```
246
+
247
+ ### Behavior Values
248
+ Control presentation and navigation:
249
+
250
+ | Behavior | Applies To | Description |
251
+ |----------|------------|-------------|
252
+ | `auto-advance` | Collections, Manifests, Canvases, Ranges | Automatically proceed to next item |
253
+ | `no-auto-advance` | Collections, Manifests, Canvases, Ranges | Do not auto-advance (default) |
254
+ | `paged` | Collections, Manifests, Ranges | Page-turning interface |
255
+ | `continuous` | Collections, Manifests, Ranges | Virtually stitch views together |
256
+ | `individuals` | Collections, Manifests, Ranges | Distinct objects/views (default) |
257
+ | `unordered` | Collections, Manifests, Ranges | No inherent order |
258
+ | `facing-pages` | Canvases | Canvas shows both parts of opening |
259
+ | `sequence` | Ranges | Alternative ordering of Canvases |
260
+ | `hidden` | Annotations, etc. | Not rendered by default |
261
+
262
+ ### Viewing Directions
263
+ - `left-to-right` (default)
264
+ - `right-to-left`
265
+ - `top-to-bottom`
266
+ - `bottom-to-top`
267
+
268
+ ---
269
+
270
+ ## Practical Integration Examples
271
+
272
+ ## Practical Integration Examples
273
+
274
+ ### Image API + Presentation API Workflow
275
+ 1. **Presentation API** provides structure and metadata via Manifests
276
+ 2. **Image API** delivers actual image content with manipulation capabilities
277
+ 3. **Annotations** link Image API resources to Canvas positions
278
+
279
+ ```json
280
+ {
281
+ "id": "https://example.org/canvas/page1",
282
+ "type": "Canvas",
283
+ "height": 1000,
284
+ "width": 750,
285
+ "items": [{
286
+ "id": "https://example.org/annopage/page1",
287
+ "type": "AnnotationPage",
288
+ "items": [{
289
+ "id": "https://example.org/annotation/page1-image",
290
+ "type": "Annotation",
291
+ "motivation": "painting",
292
+ "body": {
293
+ "id": "https://example.org/iiif/page1/full/max/0/default.jpg",
294
+ "type": "Image",
295
+ "format": "image/jpeg",
296
+ "service": [{
297
+ "id": "https://example.org/iiif/page1",
298
+ "type": "ImageService3",
299
+ "profile": "level2"
300
+ }]
301
+ },
302
+ "target": "https://example.org/canvas/page1"
303
+ }]
304
+ }]
305
+ }
306
+ ```
307
+
308
+ ### Image API Examples
309
+
310
+ ### General Examples
311
+ ```
312
+ # Full image at maximum size, default quality, JPEG format
313
+ https://example.org/image-service/abcd1234/full/max/0/default.jpg
314
+
315
+ # Square region, scaled to 200px width
316
+ https://example.org/image-service/abcd1234/square/200,/0/default.jpg
317
+
318
+ # Specific region by pixels, 50% scale, 90° rotation
319
+ https://example.org/image-service/abcd1234/125,15,120,140/pct:50/90/color.png
320
+
321
+ # Region by percentage, best fit 300x200
322
+ https://example.org/image-service/abcd1234/pct:25,25,50,50/!300,200/0/gray.jpg
323
+
324
+ # Image information document
325
+ https://example.org/image-service/abcd1234/info.json
326
+ ```
327
+
328
+ ### Riksarkivet (Swedish National Archives) Examples
329
+
330
+ **IIIF Image API 3.0:**
331
+ ```
332
+ # Base URL patterns
333
+ https://lbiiif.riksarkivet.se/{image-id}/{region}/{size}/{rotation}/{quality}.jpg
334
+ https://lbiiif.riksarkivet.se/v3/{image-id}/{region}/{size}/{rotation}/{quality}.jpg
335
+
336
+ # Full image examples
337
+ https://lbiiif.riksarkivet.se/arkis!R0001216_00005/full/max/0/default.jpg
338
+
339
+ # Square crop
340
+ https://lbiiif.riksarkivet.se/arkis!R0001216_00005/square/max/0/default.jpg
341
+
342
+ # Region by pixels (x=300, y=300, width=100, height=100)
343
+ https://lbiiif.riksarkivet.se/arkis!R0001216_00005/300,300,100,100/max/0/default.jpg
344
+
345
+ # Scale to fixed width (300px)
346
+ https://lbiiif.riksarkivet.se/arkis!R0001216_00005/full/300,/0/default.jpg
347
+
348
+ # Scale to fixed height (500px)
349
+ https://lbiiif.riksarkivet.se/arkis!R0001216_00005/full/,500/0/default.jpg
350
+
351
+ # Scale to exact dimensions (may distort aspect ratio)
352
+ https://lbiiif.riksarkivet.se/arkis!R0001216_00005/full/500,300/0/default.jpg
353
+
354
+ # 90-degree clockwise rotation
355
+ https://lbiiif.riksarkivet.se/arkis!R0001216_00005/full/max/90/default.jpg
356
+
357
+ # 90-degree rotation with horizontal flip
358
+ https://lbiiif.riksarkivet.se/arkis!R0001216_00005/full/max/!90/default.jpg
359
+ ```
360
+
361
+ **IIIF Presentation API:**
362
+ ```
363
+ # Manifest for a specific resource
364
+ https://lbiiif.riksarkivet.se/{identifier}/manifest
365
+
366
+ # Example manifest
367
+ https://lbiiif.riksarkivet.se/arkis!R0000480/manifest
368
+
369
+ # Collections (hierarchical organization)
370
+ https://lbiiif.riksarkivet.se/collection/riksarkivet
371
+ https://lbiiif.riksarkivet.se/collection/amnesomraden # Subject areas
372
+ https://lbiiif.riksarkivet.se/collection/tid # Time periods
373
+
374
+ # Collection by archive unit PID
375
+ https://lbiiif.riksarkivet.se/collection/arkiv/2Yz2ClKdn2VMeUXQcoZOO6
376
+ ```
377
+
378
+ **IIIF Content Search:**
379
+ ```
380
+ # Search within a volume
381
+ https://lbiiif.riksarkivet.se/search/arkis!40008511?q=kaffe
382
+ https://lbiiif.riksarkivet.se/search/arkis!A0068583?q=juveler
383
+ ```
384
+
385
+ ### Universal Examples (Any IIIF Server)
386
+
387
+ ## Key Implementation Notes
388
+
389
+ - Parameters must be in exact order: region/size/rotation/quality.format
390
+ - All special characters in identifiers must be URI encoded
391
+ - Operations are applied in parameter order: extract region → scale → rotate → adjust quality → convert format
392
+ - Servers SHOULD support CORS on image responses
393
+ - If region extends beyond image bounds, crop at edges rather than adding empty space
394
+ - Zero-dimension regions should return 400 Bad Request
395
+
396
+ ## Error Handling and Rate Limiting
397
+
398
+ Common HTTP status codes:
399
+ - `400 Bad Request` - Invalid parameters
400
+ - `403 Forbidden` - Missing rights marking or access denied
401
+ - `404 Not Found` - Image/resource not found
402
+ - `429 Too Many Requests` - Rate limit exceeded (check X-RateLimit-* headers)
403
+ - `501 Not Implemented` - Feature not supported
404
+
405
+ ## CORS Configuration
406
+
407
+ For external applications, configure CORS headers:
408
+ ```
409
+ # Request header
410
+ Origin: https://yourdomain.com
411
+
412
+ # Response header
413
+ Access-Control-Allow-Origin: https://yourdomain.com
414
+ ```
415
+
416
+ **Reverse Proxy Setup (recommended for external services):**
417
+
418
+ Apache HTTP Server:
419
+ ```apache
420
+ ProxyPass /iiif/ https://lbiiif.riksarkivet.se/
421
+ ProxyPassReverse /iiif/ https://lbiiif.riksarkivet.se/
422
+ Header always set Access-Control-Allow-Origin "*"
423
+ ```
424
+
425
+ Nginx:
426
+ ```nginx
427
+ location /iiif/ {
428
+ proxy_pass https://lbiiif.riksarkivet.se/;
429
+ add_header Access-Control-Allow-Origin "*";
430
+ }
431
+ ```
432
+
433
+ ## Programming Examples
434
+
435
+ ### Python: Working with IIIF Manifests and Images
436
+ ```python
437
+ import requests
438
+ import json
439
+
440
+ # Fetch and parse a IIIF Manifest
441
+ def get_manifest(manifest_url):
442
+ response = requests.get(manifest_url)
443
+ return response.json()
444
+
445
+ # Extract all image URLs from a manifest
446
+ def extract_image_urls(manifest):
447
+ image_urls = []
448
+ for canvas in manifest.get('items', []):
449
+ for annotation_page in canvas.get('items', []):
450
+ for annotation in annotation_page.get('items', []):
451
+ if annotation.get('motivation') == 'painting':
452
+ body = annotation.get('body', {})
453
+ if body.get('type') == 'Image':
454
+ image_urls.append(body.get('id'))
455
+ return image_urls
456
+
457
+ # Get image service base URL from image URL
458
+ def get_image_service_url(image_url):
459
+ # Remove the Image API parameters to get base service URL
460
+ # e.g., https://example.org/iiif/img1/full/max/0/default.jpg
461
+ # becomes https://example.org/iiif/img1
462
+ parts = image_url.split('/')
463
+ return '/'.join(parts[:-4]) # Remove /region/size/rotation/quality.format
464
+
465
+ # Generate thumbnail URL using Image API
466
+ def create_thumbnail_url(image_url, width=150, height=150):
467
+ service_url = get_image_service_url(image_url)
468
+ return f"{service_url}/full/!{width},{height}/0/default.jpg"
469
+
470
+ # Example usage
471
+ manifest_url = "https://lbiiif.riksarkivet.se/arkis!R0000480/manifest"
472
+ manifest = get_manifest(manifest_url)
473
+ images = extract_image_urls(manifest)
474
+
475
+ for img_url in images:
476
+ thumb_url = create_thumbnail_url(img_url)
477
+ print(f"Original: {img_url}")
478
+ print(f"Thumbnail: {thumb_url}")
479
+ ```
480
+
481
+ ### Python: Download Images from Riksarkivet Collection
482
+ ```python
483
+ import requests
484
+ import sys
485
+ import json
486
+ import zipfile
487
+ import re
488
+ import os
489
+
490
+ URL_BASE = 'https://lbiiif.riksarkivet.se/collection/arkiv/'
491
+
492
+ def process_collection(collection, zip_file):
493
+ for item in collection.get('items', []):
494
+ res = requests.get(item.get('id'))
495
+ if res.status_code == 200:
496
+ item_json = res.json()
497
+ if item.get('type') == 'Collection':
498
+ process_collection(item_json, zip_file)
499
+ else:
500
+ process_manifest(item_json, zip_file)
501
+
502
+ def process_manifest(manifest, zip_file):
503
+ for canvas in manifest.get('items', []):
504
+ for annotation_page in canvas.get('items', []):
505
+ for annotation in annotation_page.get('items', []):
506
+ image_url = annotation.get('body', {}).get('id')
507
+ if image_url:
508
+ regex = re.compile('.*\!(.*)\/full.*')
509
+ result = regex.match(image_url)
510
+ if result:
511
+ image_id = result.group(1)
512
+ try:
513
+ file_name = f'{image_id}.jpg'
514
+ print(f'Processing {file_name}')
515
+ download_file(image_url, file_name)
516
+ zip_file.write(file_name, file_name)
517
+ os.remove(file_name)
518
+ except Exception as e:
519
+ print(e)
520
+
521
+ def download_file(url, file_name):
522
+ with requests.get(url, stream=True) as r:
523
+ r.raise_for_status()
524
+ with open(file_name, 'wb') as f:
525
+ for chunk in r.iter_content(chunk_size=8192):
526
+ f.write(chunk)
527
+
528
+ def main():
529
+ if len(sys.argv) > 1:
530
+ pid = sys.argv[1]
531
+ res = requests.get(f'{URL_BASE}{pid}')
532
+ if res.status_code == 200:
533
+ collection = res.json()
534
+ with zipfile.ZipFile(f'{pid}.zip', 'w') as zip_file:
535
+ process_collection(collection, zip_file)
536
+ else:
537
+ print('Usage: download.py <pid>')
538
+
539
+ if __name__ == "__main__":
540
+ main()
541
+ ```
542
+
543
+ ### JavaScript: IIIF Viewer Integration
544
+ ```javascript
545
+ // Universal Viewer integration
546
+ const manifestUri = 'https://lbiiif.riksarkivet.se/arkis!R0000480/manifest';
547
+ const uv = new UV.createUV('#uv-container', {
548
+ manifestUri: manifestUri,
549
+ configUri: '/uv-config.json'
550
+ });
551
+
552
+ // Mirador viewer integration
553
+ const mirador = Mirador.viewer({
554
+ id: 'mirador-container',
555
+ windows: [{
556
+ manifestId: manifestUri,
557
+ canvasId: 'https://lbiiif.riksarkivet.se/arkis!R0000480/canvas/1'
558
+ }]
559
+ });
560
+
561
+ // OpenSeadragon with IIIF Image service
562
+ const viewer = OpenSeadragon({
563
+ id: 'osd-container',
564
+ tileSources: {
565
+ '@context': 'http://iiif.io/api/image/3/context.json',
566
+ '@id': 'https://lbiiif.riksarkivet.se/arkis!R0000480_00001',
567
+ 'profile': 'level1'
568
+ }
569
+ });
570
+
571
+ // Fetch manifest and display metadata
572
+ async function displayManifest(manifestUrl) {
573
+ const response = await fetch(manifestUrl);
574
+ const manifest = await response.json();
575
+
576
+ // Display basic info
577
+ const title = manifest.label?.en?.[0] || manifest.label?.sv?.[0] || 'Untitled';
578
+ const summary = manifest.summary?.en?.[0] || manifest.summary?.sv?.[0] || '';
579
+
580
+ document.getElementById('title').textContent = title;
581
+ document.getElementById('summary').textContent = summary;
582
+
583
+ // Display metadata
584
+ const metadataContainer = document.getElementById('metadata');
585
+ manifest.metadata?.forEach(item => {
586
+ const label = item.label?.en?.[0] || item.label?.sv?.[0] || '';
587
+ const value = item.value?.en?.[0] || item.value?.sv?.[0] || '';
588
+
589
+ const div = document.createElement('div');
590
+ div.innerHTML = `<strong>${label}:</strong> ${value}`;
591
+ metadataContainer.appendChild(div);
592
+ });
593
+ }
594
+ ```
595
+
596
+ ### Finding Image IDs from Archive Units
597
+ 1. Get archive unit PID from search interface
598
+ 2. Fetch collection data: `https://lbiiif.riksarkivet.se/collection/arkiv/{pid}`
599
+ 3. Extract manifest URLs from `items` array
600
+ 4. Parse image IDs from manifest image URLs
601
+
602
+ ### IIIF Presentation API Structure
603
+
604
+ **Collection Response Example:**
605
+ ```json
606
+ {
607
+ "id": "https://lbiiif.riksarkivet.se/collection/arkiv/2Yz2ClKdn2VMeUXQcoZOO6",
608
+ "type": "Collection",
609
+ "label": { "sv": ["1 (1654-1721) - Handlingar rörande förhandlingar..."] },
610
+ "summary": { "sv": ["Referenskod: SE/RA/2113/2113.2/1"] },
611
+ "items": [
612
+ {
613
+ "id": "https://lbiiif.riksarkivet.se/arkis!R0000480/manifest",
614
+ "type": "Manifest",
615
+ "label": { "sv": ["1 (1654-1721) - R0000480 - Handlingar..."] }
616
+ }
617
+ ]
618
+ }
619
+ ```
620
+
621
+ **Hierarchy:**
622
+ - **Collection** → Contains other Collections or Manifests
623
+ - **Manifest** → Contains Canvases (individual pages/images)
624
+ - **Canvas** → Contains image annotations with Image API URLs
625
+
626
+ ## Common Use Cases
627
+
628
+ ### Image API
629
+ - **Thumbnails** - Quick generation of preview images at specific sizes
630
+ - **Deep zoom viewers** - Requesting tiles and regions for interactive viewing
631
+ - **Responsive images** - Serving appropriate sizes for different devices
632
+ - **Image analysis** - Extracting specific regions for processing
633
+ - **Print quality** - High-resolution downloads with rotation/cropping
634
+
635
+ ### Presentation API
636
+ - **Digital libraries** - Organizing books, manuscripts, and documents
637
+ - **Museum collections** - Presenting artworks with metadata and context
638
+ - **Archives** - Hierarchical organization of historical materials
639
+ - **Educational platforms** - Structured learning materials with annotations
640
+ - **Cultural heritage** - Multi-language, multi-institutional content sharing
641
+
642
+ ### Combined Workflows
643
+ - **Reading room interfaces** - Full manuscripts with page-turning and zoom
644
+ - **Annotation tools** - Transcription and commentary systems
645
+ - **Comparative viewing** - Side-by-side analysis of similar materials
646
+ - **Mobile apps** - Responsive cultural heritage exploration
647
+ - **Research platforms** - Advanced search and analysis tools
648
+
649
+ ## Implementation Notes
650
+
651
+ ### Content Delivery Best Practices
652
+ - Use Image API for dynamic image manipulation and delivery
653
+ - Use Presentation API for metadata, structure, and viewing instructions
654
+ - Combine both APIs for complete digital object presentation
655
+ - Implement proper caching strategies for performance
656
+ - Consider CDN deployment for global access
657
+
658
+ ### Client Application Patterns
659
+ 1. **Parse Manifest** → Extract structure and metadata
660
+ 2. **Render Canvas** → Display individual views/pages
661
+ 3. **Load Images** → Use Image API services for content
662
+ 4. **Handle Annotations** → Process transcriptions, translations, comments
663
+ 5. **Navigate Structure** → Use Ranges for table of contents
664
+ 6. **Apply Behaviors** → Follow presentation hints (paging, auto-advance, etc.)
665
+
666
+ ### Data Flow
667
+ ```
668
+ Collection → Manifest → Canvas → Annotation → Image Service
669
+ ↓ ↓ ↓ ↓ ↓
670
+ Hierarchy Metadata Viewport Association Pixels
671
+ ```
672
+
673
+ ## Implementation Variations
674
+
675
+ ### Riksarkivet (Swedish National Archives) Specifics
676
+ **Technical Implementation:**
677
+ - **Compliance Level**: Image API Level 1 (basic features)
678
+ - **Supported Formats**: JPEG only (`.jpg`)
679
+ - **Supported Quality**: `default` only
680
+ - **Version Support**: Both IIIF 2.0 and 3.0 APIs
681
+ - **Content Types**:
682
+ - Images: `content-type: image/jpeg`
683
+ - Manifests: `content-type: application/json`
684
+ - **Access Rights**: Public digitized archives older than 110 years
685
+ - **Rate Limiting**: Enforced with `X-RateLimit-*` headers
686
+
687
+ **Content Organization:**
688
+ - Collections organized by subject (`amnesomraden`) and time (`tid`)
689
+ - Archive units identified by persistent IDs (PIDs)
690
+ - Manifests correspond to volumes or individual items
691
+ - Search integration with full-text OCR content
692
+
693
+ **API Endpoints:**
694
+ - Image API: `https://lbiiif.riksarkivet.se/`
695
+ - Collections: `https://lbiiif.riksarkivet.se/collection/`
696
+ - Search: `https://lbiiif.riksarkivet.se/search/`
697
+
698
+ ### General IIIF Implementation Patterns
699
+
700
+ **Compliance Levels (Image API):**
701
+ - **Level 0**: Static images with limited manipulation
702
+ - **Level 1**: Basic resize, rotation, quality options
703
+ - **Level 2**: Full specification support with advanced features
704
+
705
+ **Common Institution Patterns:**
706
+ - **Museums**: Focus on high-quality images with rich metadata
707
+ - **Libraries**: Emphasis on text materials with OCR and search
708
+ - **Archives**: Hierarchical organization with finding aids
709
+ - **Universities**: Research-focused with annotation tools
710
+
711
+ **Supported IIIF APIs (Typical Implementations):**
712
+ - ✅ **Image API 3.0/2.0** - Core image delivery (universal)
713
+ - ✅ **Presentation API 3.0** - Metadata and structure (most institutions)
714
+ - ✅ **Content Search API 1.0** - Full-text search (text-heavy collections)
715
+ - ⚠️ **Authentication API 1.0** - Access control (restricted content)
716
+ - ⚠️ **Change Discovery API 1.0** - Update notifications (large institutions)
717
+
718
+ ### Server Technology Stacks
719
+
720
+ **Popular IIIF Server Software:**
721
+ - **Cantaloupe** - Java-based image server (Image API)
722
+ - **IIPImage** - C++ high-performance server
723
+ - **Loris** - Python image server
724
+ - **RIIIF** - Ruby implementation
725
+ - **Omeka S** - Content management with IIIF support
726
+ - **Samvera/Hyrax** - Digital repository platform
727
+ - **DSpace** - Institutional repository with IIIF modules
728
+
729
+ **Cloud Solutions:**
730
+ - **IIIF Hosting** - Managed IIIF services
731
+ - **AWS/Azure/GCP** - Serverless IIIF implementations
732
+ - **ContentDM** - OCLC's hosted digital collections platform
733
+
734
+ ## Integration with Viewers
735
+
736
+ ### Popular IIIF-Compatible Viewers
737
+
738
+ **Full-Featured Viewers:**
739
+ - **Universal Viewer** - Complete presentation with navigation and metadata
740
+ - **Mirador** - Advanced viewer with workspace and comparison features
741
+ - **Tify** - Vue.js-based viewer for modern web applications
742
+
743
+ **Specialized Viewers:**
744
+ - **OpenSeadragon** - High-performance pan/zoom for images
745
+ - **Leaflet-IIIF** - Map-style tile viewer for large images
746
+ - **Annona** - Lightweight annotation-focused viewer
747
+
748
+ **Implementation Examples:**
749
+ ```javascript
750
+ // Universal Viewer (comprehensive)
751
+ const manifestUri = 'https://lbiiif.riksarkivet.se/arkis!R0000480/manifest';
752
+ const uv = new UV.createUV('#uv', { manifestUri: manifestUri });
753
+
754
+ // Mirador (research-focused)
755
+ const mirador = Mirador.viewer({
756
+ id: 'mirador',
757
+ windows: [{ manifestId: manifestUri }],
758
+ workspaceControlPanel: { enabled: true }
759
+ });
760
+
761
+ // OpenSeadragon (image-focused)
762
+ const viewer = OpenSeadragon({
763
+ id: 'osd',
764
+ tileSources: 'https://example.org/iiif/image1/info.json'
765
+ });
766
+ ```
767
+
768
+ ### Mobile and Responsive Considerations
769
+ - Progressive image loading for bandwidth optimization
770
+ - Touch-friendly zoom and pan interactions
771
+ - Adaptive metadata display for small screens
772
+ - Offline capability for downloaded content
773
+ - Platform-specific apps (iOS/Android) using IIIF APIs