-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Recipe #309 annotation collections #521
Changes from 13 commits
764b5e5
84657f3
947c13a
fae2109
c002dc6
c8629e8
c858ffa
84cc61b
b4a5b08
15ce65e
363c005
89cae76
e6e65f1
37b664f
038efda
3d38d59
a1b5bb4
ad13968
c38ff45
a5ce41b
3c5baaf
9077a76
9aaa55b
8827f8e
6328c22
2131874
35fb52d
4a6c51f
4cd8739
3247eb6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"@context": "http://iiif.io/api/presentation/3/context.json", | ||
"id": "{{ id.url }}", | ||
"type": "AnnotationCollection", | ||
"label": { | ||
"en": [ | ||
"Newspaper layout markup" | ||
] | ||
}, | ||
"total": 8, | ||
"first": "{{ id.path }}/anno_p1.json", | ||
"last": "{{ id.path }}/anno_p2.json" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
{ | ||
"@context": "http://iiif.io/api/presentation/3/context.json", | ||
"id": "{{ id.url }}", | ||
"type": "AnnotationPage", | ||
"partOf": [{ | ||
"id": "{{ id.path }}/anno_coll.json", | ||
"type": "AnnotationCollection" | ||
}], | ||
"next": "{{ id.path }}/anno_p2.json", | ||
"items": [ | ||
{ | ||
"id": "{{ id.url }}-1", | ||
"type": "Annotation", | ||
"motivation": "tagging", | ||
"body": { | ||
"type": "TextualBody", | ||
"format": "text/plain", | ||
"value": "text-1-1" | ||
}, | ||
"target": { | ||
"type": "SpecificResource", | ||
"source": { | ||
"id": "{{ id.path }}/canvas/p1", | ||
"type": "Canvas", | ||
"partOf": [{ | ||
"id": "{{ id.path }}/manifest.json", | ||
"type": "Manifest" | ||
}] | ||
}, | ||
"selector": { | ||
"type": "FragmentSelector", | ||
"conformsTo": "http://www.w3.org/TR/media-frags/", | ||
"value": "xywh=88,957,2768,248" | ||
} | ||
} | ||
}, | ||
{ | ||
"id": "{{ id.url }}-2", | ||
"type": "Annotation", | ||
"motivation": "tagging", | ||
"body": { | ||
"type": "TextualBody", | ||
"format": "text/plain", | ||
"value": "text-1-2" | ||
}, | ||
"target": { | ||
"type": "SpecificResource", | ||
"source": { | ||
"id": "{{ id.path }}/canvas/p1", | ||
"type": "Canvas", | ||
"partOf": [{ | ||
"id": "{{ id.path }}/manifest.json", | ||
"type": "Manifest" | ||
}] | ||
}, | ||
"selector": { | ||
"type": "FragmentSelector", | ||
"conformsTo": "http://www.w3.org/TR/media-frags/", | ||
"value": "xywh=80,1181,928,3384" | ||
} | ||
} | ||
}, | ||
{ | ||
"id": "{{ id.url }}-3", | ||
"type": "Annotation", | ||
"motivation": "tagging", | ||
"body": { | ||
"type": "TextualBody", | ||
"format": "text/plain", | ||
"value": "text-1-3" | ||
}, | ||
"target": { | ||
"type": "SpecificResource", | ||
"source": { | ||
"id": "{{ id.path }}/canvas/p1", | ||
"type": "Canvas", | ||
"partOf": [{ | ||
"id": "{{ id.path }}/manifest.json", | ||
"type": "Manifest" | ||
}] | ||
}, | ||
"selector": { | ||
"type": "FragmentSelector", | ||
"conformsTo": "http://www.w3.org/TR/media-frags/", | ||
"value": "xywh=1000,2693,1880,1824" | ||
} | ||
} | ||
}, | ||
{ | ||
"id": "{{ id.url }}-4", | ||
"type": "Annotation", | ||
"motivation": "tagging", | ||
"body": { | ||
"type": "TextualBody", | ||
"format": "text/plain", | ||
"value": "text-2" | ||
}, | ||
"target": { | ||
"type": "SpecificResource", | ||
"source": { | ||
"id": "{{ id.path }}/canvas/p1", | ||
"type": "Canvas", | ||
"partOf": [{ | ||
"id": "{{ id.path }}/manifest.json", | ||
"type": "Manifest" | ||
}] | ||
}, | ||
"selector": { | ||
"type": "FragmentSelector", | ||
"conformsTo": "http://www.w3.org/TR/media-frags/", | ||
"value": "xywh=992,1213,1904,1472" | ||
} | ||
} | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
{ | ||
"@context": "http://iiif.io/api/presentation/3/context.json", | ||
"id": "{{ id.url }}", | ||
"type": "AnnotationPage", | ||
"partOf": [{ | ||
"id": "{{ id.path }}/anno_coll.json", | ||
"type": "AnnotationCollection" | ||
}], | ||
"prev": "{{ id.path }}/anno_p1.json", | ||
"items": [ | ||
{ | ||
"id": "{{ id.url }}-1", | ||
"type": "Annotation", | ||
"motivation": "tagging", | ||
"body": { | ||
"type": "TextualBody", | ||
"format": "text/plain", | ||
"value": "text-3-1" | ||
}, | ||
"target": { | ||
"type": "SpecificResource", | ||
"source": { | ||
"id": "{{ id.path }}/canvas/p2", | ||
"type": "Canvas", | ||
"partOf": [{ | ||
"id": "{{ id.path }}/manifest.json", | ||
"type": "Manifest" | ||
}] | ||
}, | ||
"selector": { | ||
"type": "FragmentSelector", | ||
"conformsTo": "http://www.w3.org/TR/media-frags/", | ||
"value": "xywh=856,381,928,4200" | ||
} | ||
} | ||
}, | ||
{ | ||
"id": "{{ id.url }}-2", | ||
"type": "Annotation", | ||
"motivation": "tagging", | ||
"body": { | ||
"type": "TextualBody", | ||
"format": "text/plain", | ||
"value": "text-3-2" | ||
}, | ||
"target": { | ||
"type": "SpecificResource", | ||
"source": { | ||
"id": "{{ id.path }}/canvas/p2", | ||
"type": "Canvas", | ||
"partOf": [{ | ||
"id": "{{ id.path }}/manifest.json", | ||
"type": "Manifest" | ||
}] | ||
}, | ||
"selector": { | ||
"type": "FragmentSelector", | ||
"conformsTo": "http://www.w3.org/TR/media-frags/", | ||
"value": "xywh=1784,2461,952,2064" | ||
} | ||
} | ||
}, | ||
{ | ||
"id": "{{ id.url }}-3", | ||
"type": "Annotation", | ||
"motivation": "tagging", | ||
"body": { | ||
"type": "TextualBody", | ||
"format": "text/plain", | ||
"value": "text-3-3" | ||
}, | ||
"target": { | ||
"type": "SpecificResource", | ||
"source": { | ||
"id": "{{ id.path }}/canvas/p2", | ||
"type": "Canvas", | ||
"partOf": [{ | ||
"id": "{{ id.path }}/manifest.json", | ||
"type": "Manifest" | ||
}] | ||
}, | ||
"selector": { | ||
"type": "FragmentSelector", | ||
"conformsTo": "http://www.w3.org/TR/media-frags/", | ||
"value": "xywh=2736,2485,816,2064" | ||
} | ||
} | ||
}, | ||
{ | ||
"id": "{{ id.url }}-4", | ||
"type": "Annotation", | ||
"motivation": "tagging", | ||
"body": { | ||
"type": "TextualBody", | ||
"format": "text/plain", | ||
"value": "text-4" | ||
}, | ||
"target": { | ||
"type": "SpecificResource", | ||
"source": { | ||
"id": "{{ id.path }}/canvas/p2", | ||
"type": "Canvas", | ||
"partOf": [{ | ||
"id": "{{ id.path }}/manifest.json", | ||
"type": "Manifest" | ||
}] | ||
}, | ||
"selector": { | ||
"type": "FragmentSelector", | ||
"conformsTo": "http://www.w3.org/TR/media-frags/", | ||
"value": "xywh=1792,373,1744,2064" | ||
} | ||
} | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
--- | ||
title: Using Annotation Collections | ||
id: 309 | ||
layout: recipe | ||
tags: [tbc] | ||
summary: "tbc" | ||
viewers: | ||
topic: | ||
- basic | ||
--- | ||
|
||
## Use Case | ||
|
||
You have a large number of Annotations covering multiple Canvases in a Manifest, for example crowd-sourced transcriptions or the output from a layout analysis algorithm and you want the Annotations to be displayed in a viewer as a recognizable group over the document with a label and a common color. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps lead with one of the examples as the case and then the technical terms followed by the analogous use case examples. |
||
|
||
## Implementation Notes | ||
|
||
The [IIIF Presentation API 3](https://iiif.io/api/presentation/3.0/#58-annotation-collection) defines the AnnotationCollection as a mechanism to represent groupings of AnnotationPages that should be managed as a single whole, regardless of which Canvas or resource they target. The AnnotationCollection is a separate document that references a chain of one or more separate AnnotationPages containing the Annotations. The AnnotationPages contain a reference to the parent AnnotationCollection and a reference to the next page in the chain. | ||
|
||
The AnnotationCollection should have a `label` property that can be shown to the user and it can optionally contain additional properties as specified in the [IIIF Presentation API 3](https://iiif.io/api/presentation/3.0/#a-summary-of-property-requirements). | ||
|
||
The AnnotationCollection has a `first` property that contains the URI of the first AnnotationPage in the sequence, a `last` property that contains the URI of the last AnnotationPage and it should have a `total` property that contains the total number of Annotations in the collection. | ||
|
||
The IIIF Manifest requires that Annotations that should be shown on a Canvas are contained in AnnotationPages referenced in the `annotations` property of that Canvas. This means that all Annotations need to be grouped by Canvas and put into one or more AnnotationPages per Canvas. An AnnotationPage can not contain Annotations for more than one Canvas. | ||
|
||
The AnnotationPages have an `items` property containing the list of Annotations, a `partOf` property that contains the URI of the parent AnnotationCollection, and `next` and `prev` properties that contain the URIs of the next and previous AnnotationPages in the sequence. AnnotationPages are often separate documents that are [referenced][0269] in the manifest using a reference object that can additionally provide some properties for access inside the manifest. | ||
|
||
A IIIF viewer that displays Annotations on a Canvas follows the URIs in the `annotations` property of the Canvas and loads the Annotations in the referenced AnnotationPages. If the viewer wants to indicate that these Annotations belong to one or more AnnotationCollections it has to follow the URI in the `partOf` property of the AnnotationPages to identify the AnnotationCollection and display its label and choose a common color for the Annotations. The indirect connection from the Manifest to the AnnotationCollection means that a viewer would have to load all AnnotationPages from all Canvases if it wants to present a complete list of all AnnotationCollections in the Manifest to the user. This potentially slow process can be avoided if the `partOf`, `next`, and `prev` properties of the AnnotationPages are provided in the reference object inside the Manifest like in the example below. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a little odd where it is expressing guidance for viewer designers. The language of a recipe (I think) should be to the Manifest host, explaining how to express presentation preferences to the viewers. The advice is solid, however. |
||
|
||
## Example | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a lot to take in. I wouldn't delay posting it, but a diagram may be helpful here, in the flavor of those provided in the APIs. |
||
|
||
We use a Manifest containing two pages from a newspaper (Berliner Tageblatt, February 16, 1925, from Staatsbibliothek Berlin via Europeana) and a set of Annotations concerning layout and reading order. | ||
|
||
The Annotations select rectangular regions on the Canvases in the Manifest and add textual tags describing layout elements. They are contained in two AnnotationPages "anno_p1.json" for Annotations on the first Canvas and "anno_p2.json" for Annotations on the second Canvas. "anno_p1.json" contains a `next` reference to "anno_p2.json", "anno_p2.json" contains a `prev` reference to "anno_p1.json", and both pages contain a `partOf` reference to the AnnotationCollection. | ||
|
||
The AnnotationCollection is in the file "anno_coll.json". It has a `label` and references "anno_p1.json" as the `first` and "anno_p2.json" as the `last` page and contains the `total` number of Annotations. | ||
|
||
The AnnotationCollection referencing the AnnotationPages: | ||
|
||
{% include jsonviewer.html src="anno_coll.json" %} | ||
|
||
The Manifest containing the two Canvases and referencing the AnnotationPages: | ||
|
||
{% include manifest_links.html viewers="" manifest="manifest.json" %} | ||
|
||
{% include jsonviewer.html src="manifest.json" %} | ||
|
||
The first AnnotationPage with Annotations on the first Canvas: [anno_p1.json](anno_p1.json) | ||
|
||
The second AnnotationPage with Annotations on the second Canvas: [anno_p2.json](anno_p2.json) | ||
|
||
## Related Recipes | ||
|
||
* [Embedded or Referenced Annotations][0269] for referencing Annotations in external AnnotationPages | ||
* [Simple Annotation - Tagging][0021] annotating a rectangular Canvas region | ||
* [Annotation with a Non-Rectangular Polygon][0261] annotating an irregular shape on a Canvas | ||
|
||
{% include acronyms.md %} | ||
{% include links.md %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The title seems more like a tutorial than a recipe. If I were looking for this, I would be searching for terms from the use case