Skip to content

Commit bf008fa

Browse files
committed
expansion of content state desc in P4 index.md
1 parent 923d840 commit bf008fa

File tree

2 files changed

+369
-12
lines changed

2 files changed

+369
-12
lines changed

source/presentation/4.0/index.md

Lines changed: 368 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -361,25 +361,383 @@ use totalItems? https://iiif.io/api/discovery/1.0/#totalitems
361361

362362
## Content State
363363

364-
(introduce motivation and reasons)
364+
A Content State is simply any valid IIIF Presentation Resource, or part of a Presentation resource. The following are all Content States that describe a "fragment" of IIIF:
365365

366-
Separate Content State Sharing spec (protocols for sharing annotations)
366+
A "bare" Manifest URI:
367367

368-
content state intended to:
368+
```
369+
https://example.org/manifests/1
370+
```
369371

370-
- load a view of some resource (existing spec)
371-
- load a view of some resource AND modify the Container (show you my new anno, add camera)
372-
- modify the Container in a particular context (`scope`, storytelling)
373-
- contribute additional information permanently (rerum **inbox** - move to protocol doc)
372+
A reference to a Manifest:
374373

375-
### Using Content State
374+
```json
375+
{
376+
"id": "https://example.org/manifests/1",
377+
"type": "Manifest"
378+
}
379+
```
380+
381+
A region of a Canvas within a Manifest:
382+
383+
```json
384+
{
385+
"id": "https://example.org/canvases/aabb#xywh=4500,1266,600,600",
386+
"type": "Canvas",
387+
"partOf": {
388+
"id": "https://example.org/manifests/1",
389+
"type": "Manifest"
390+
}
391+
}
392+
```
393+
394+
Two versions of a painting from different publishers:
395+
396+
```json
397+
[
398+
{
399+
"id": "https://gallery-1.org/iiif/sunflowers/canvas1",
400+
"type": "Canvas",
401+
"partOf": [
402+
{
403+
"id": "https://gallery-1.org/iiif/sunflowers",
404+
"type": "Manifest"
405+
}
406+
]
407+
},
408+
{
409+
"id": "https://gallery-2.org/collection/sunflowers/c1",
410+
"type": "Canvas",
411+
"partOf": [
412+
{
413+
"id": "https://gallery-2.org/collection/sunflowers",
414+
"type": "Manifest"
415+
}
416+
]
417+
}
418+
]
419+
```
420+
421+
A Scene with a Camera at a particular point:
422+
423+
424+
```json
425+
{
426+
"id": "https://example.org/iiif/scene1/page/p1/1",
427+
"type": "Scene",
428+
"items": [
429+
{
430+
"id": "https://example.org/iiif/3d/anno8",
431+
"type": "Annotation",
432+
"motivation": ["painting"],
433+
"body": {
434+
"type": "SpecificResource",
435+
"source": [
436+
{
437+
"id": "https://example.org/iiif/3d/cameras/1",
438+
"type": "PerspectiveCamera",
439+
"label": {
440+
"en": [
441+
"Perspective Camera Pointed At Front of Cranium and Mandible"
442+
]
443+
},
444+
"fieldOfView": 50.0,
445+
"near": 0.1,
446+
"far": 2000.0
447+
}
448+
]
449+
},
450+
"target": {
451+
"type": "SpecificResource",
452+
"source": [
453+
{
454+
"id": "https://example.org/iiif/scene1",
455+
"type": "Scene"
456+
}
457+
],
458+
"selector": [
459+
{
460+
"type": "PointSelector",
461+
"x": 0.0, "y": 0.15, "z": 0.75
462+
}
463+
]
464+
}
465+
}
466+
]
467+
}
468+
```
469+
470+
The term _Content State_ is used for any arbitrary fragments of IIIF such as the above when they are used in the particular ways defined by this specification. A Content State is **usually** carried by the `target` of an annotation with the motivation `contentState`, or `body` of an annotation with the motivation `activating`, but in some scenarios may be transferred between client applications without an enclosing annotation, as a "bare" URI (see Content State 2.0 specification).
471+
472+
Content States are used for the following applications:
473+
474+
### Load a particular view of a resource or group of resources
475+
476+
In this usage, an annotation with the motivation `contentState` is passed to a client to initialize it with a particular view of a resource. Almost all IIIF Clients initialize from the very simplest form of Content State - a Manifest URI. A more complex Content State might target a particular region of a particular canvas within a Manifest, as in the second example above. A client initialized from such a Content State would load the Manifest, show the particular Canvas, and perhaps zoom in on the target region.
477+
478+
The mechanisms for passing Content State into a client, and exporting a Content State from a client, are given in the [Content State Protocol API 2.0](content-state-2) specification, which describes the scenarios in which a URI, or Content State not carried by an annotation, should be interpreted by a Client as a Content State.
479+
480+
481+
### Load a particular view of some resource and modify it
482+
483+
In the previous usage, the fragment of IIIF carried by the annotation with the motivation `contentState` provides enough information for a Client to load a resource and show it. This fragment can also carry additional IIIF Presentation API resources not shown in the referred-to resource. For example, in the following example the Content State carries additional annotations not present in the original published Manifest. A client initializing from this Content State would show these additional annotations to the user:
484+
485+
```json
486+
{
487+
"id": "https://example.org/import/3",
488+
"type": "Annotation",
489+
"motivation": "contentState",
490+
"target": {
491+
"id": "https://example.org/canvases/aabb#xywh=4500,1266,600,600",
492+
"type": "Canvas",
493+
"partOf": {
494+
"id": "https://example.org/manifests/nook12",
495+
"type": "Manifest"
496+
},
497+
"annotations": [
498+
{
499+
"id": "https://my-annotation-store.org/user4532/notes-on-book12/p1",
500+
"type": "AnnotationPage"
501+
}
502+
]
503+
}
504+
}
505+
```
506+
507+
As well as adding resources not present in the referred-to resource, the Content State can also remove parts of the referred-to resource from the user's view by applying the behavior `hidden` to them:
508+
509+
```jsonc
510+
{
511+
// What does this actually look like? I want to load bnf_chateauroux example but HIDE the illumination
512+
// ...
513+
"id": "https://iiif.io/api/cookbook/recipe/0036-composition-from-multiple-images/annotation/p0001-image",
514+
"type": "Annotation",
515+
"motivation": "painting",
516+
"behavior": ["hidden"]
517+
}
518+
```
519+
520+
TODO: what is the processing algorithm for applying incoming `hidden` ?
521+
522+
When a Content State annotation carries a Scene, a view might be initialized from a Content State that introduces an additional Camera that shows the user the point of interest.
523+
524+
525+
### Modify the Container in a particular context
526+
527+
The techniques in the previous example are also used within a published IIIF Manifest to modify the contents of a Container in the contexts of different annotations on that Container. This technique allows IIIF to be used for _storytelling_ and other narrative applications beyond simply conveying a static Digital Object into a viewer and leaving subsequent interactions entirely in the control of the user. The `scope` property indicates to the client that the Content State provides valuable context for displaying some aspect of a Scene or other Container. In the case of a commenting annotation, this means that the Content State should be loaded when the commenting annotation is selected or otherwise highlighted.
528+
529+
530+
Consider a Scene with two models, and two `commenting` annotations:
531+
532+
```jsonc
533+
{
534+
"id": "https://example.org/iiif/3d/whale_comment_scope_content_state.json",
535+
"type": "Manifest",
536+
"label": { "en": ["Whale Cranium and Mandible with Dynamic Commenting Annotations and Custom Per-Anno Views"] },
537+
"items": [
538+
{
539+
"id": "https://example.org/iiif/scene1/page/p1/1",
540+
"type": "Scene",
541+
"label": { "en": ["A Scene Containing a Whale Cranium and Mandible"] },
542+
"items": [
543+
{
544+
"id": "https://example.org/iiif/scene1/page/p1/1",
545+
"type": "AnnotationPage",
546+
"items": [
547+
{
548+
"id": "https://example.org/iiif/3d/anno1",
549+
"type": "Annotation",
550+
"motivation": ["painting"],
551+
"body": {
552+
"id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/whale/whale_mandible.glb",
553+
"type": "Model"
554+
},
555+
"target": {
556+
// SpecificResource with PointSelector
557+
}
558+
},
559+
{
560+
"id": "https://example.org/iiif/3d/anno2",
561+
"type": "Annotation",
562+
"motivation": ["painting"],
563+
"body": {
564+
"id": "https://raw.githubusercontent.com/IIIF/3d/main/assets/whale/whale_cranium.glb",
565+
"type": "Model"
566+
},
567+
"target": {
568+
// SpecificResource with PointSelector
569+
}
570+
}
571+
]
572+
}
573+
]
574+
}
575+
],
576+
"annotations": [
577+
{
578+
"id": "https://example.org/iiif/scene1/page/p1/annotations/1",
579+
"type": "AnnotationPage",
580+
"items": [
581+
{
582+
"id": "https://example.org/iiif/3d/anno7",
583+
"type": "Annotation",
584+
"motivation": ["commenting"],
585+
"bodyValue": "Mandibular tooth",
586+
"target": {
587+
// SpecificResource with PointSelector
588+
}
589+
},
590+
{
591+
"id": "https://example.org/iiif/3d/anno5",
592+
"type": "Annotation",
593+
"motivation": ["commenting"],
594+
"bodyValue": "Right pterygoid hamulus",
595+
"target": {
596+
// SpecificResource with PointSelector
597+
}
598+
}
599+
]
600+
}
601+
]
602+
}
603+
```
604+
605+
In that form, the user is left to interpret the commenting annotations and explore the Scene. The client will render a UI that presents the two commenting annotation in some form and allow the user to navigate between them. The commenting annotations are ordered; while the user might explore them freely in the Scene they might also go "forward" from the first to the second commenting annotation and "back" to the first from the second.
606+
607+
In many complex 3D Scenes, it may not be clear what or how to look at a particular point of interest even when the commenting annotation targets a particular point. The view may be occluded by parts of the model, or other models in the Scene. It may be useful to light the Scene differently in different contexts.
608+
609+
In the same way an incoming Content State can modify a Scene as it initializes the client, so can a Content State attached to each (non-`painting`) annotation target modify the Scene as the user moves between different annotations.
610+
611+
The `scope` property of an annotation `target` provides _contextual_ Content State - the viewer should modify the Scene by applying the Content State carried by the `scope` property _only when the user is in the context of that annotation_.
612+
613+
Taking the first commenting annotation from the above example and adding a `scope` property, whose value is an annotation with the motivation `contentState`, we can introduce a new Camera specifically for this particular annotation, so that when the user selects this comment, the client will switch the view to this camera. This example also changes the background color of the Scene:
614+
615+
```jsonc
616+
{
617+
"id": "https://example.org/iiif/3d/anno7",
618+
"type": "Annotation",
619+
"motivation": ["commenting"],
620+
"bodyValue": "Mandibular tooth",
621+
"target": {
622+
623+
// SpecificResource with PointSelector
624+
// "type": "SpecificResource",
625+
// "source": ... the Scene...
626+
// "selector": ... a point ...
627+
628+
"scope": { // a modification to the Scene, only in the context of this annotation
629+
630+
"id": "https://example.org/iiif/3d/anno4",
631+
"type": "Annotation",
632+
"motivation": ["contentState"],
633+
"target": {
634+
"id": "https://example.org/iiif/scene1/page/p1/1",
635+
"type": "Scene",
636+
"backgroundColor": "yellow",
637+
"items": [
638+
{
639+
"id": "https://example.org/iiif/3d/anno8",
640+
"type": "Annotation",
641+
"motivation": ["painting"],
642+
"body": {
643+
"type": "SpecificResource",
644+
"source": [
645+
{
646+
"id": "https://example.org/iiif/3d/cameras/1",
647+
"type": "PerspectiveCamera",
648+
"label": {"en": ["Perspective Camera Pointed At Front of Cranium and Mandible"]},
649+
"fieldOfView": 50.0,
650+
"near": 0.10,
651+
"far": 2000.0
652+
}
653+
]
654+
},
655+
"target": {
656+
"type": "SpecificResource",
657+
"source": [
658+
{
659+
"id": "https://example.org/iiif/scene1",
660+
"type": "Scene"
661+
}
662+
],
663+
"selector": [
664+
{
665+
"type": "PointSelector",
666+
"x": 0.0, "y": 0.15, "z": 0.75
667+
}
668+
]
669+
}
670+
}
671+
]
672+
}
673+
}
674+
}
675+
}
676+
```
677+
678+
In a storytelling or exhibition scenario, the non-painting `annotations` might be carrying informative text, or even rich HTML bodies. They can be considered to be _steps_ in the story. The use of `scope` allows a precise storytelling experience to be specified, including:
679+
680+
- providing a specific viewpoint for each step of the narrative (or even a choice of viewpoints)
681+
- modifying the lighting of the Scene for each step, for example shining a spotlight on a point of interest
682+
- hiding parts of the Scene for a step
683+
- introducing additional models at a particular step
684+
- (and many more!)
685+
686+
Use of `scope` is permitted in annotations on any Container type, not just Scenes. For example, a 2D narrative around a Canvas might show or hide different `painting` annotations at each step.
687+
688+
#### The `sequence` behavior
689+
690+
// Is this right? Language...
691+
692+
While all AnnotationPage `items` are inherently ordered, an Annotation Page with the behavior `sequence` is explicitly a narrative, and clients should prevent (dissuade) users from jumping about. The presence of `sequence` affects the way a client should interpret the `reset` property described below.
693+
694+
### Content States on Manifests
695+
696+
When an annotation with the motivation `contentState` is provided via the `annotations` property of a Manifest, rather than contextually via `scope`, it is assumed to be generally available for selection by the user at any time. A client may present such as annotations as a menu of views, allowing arbitrary jumping into any Scene (or Canvas or Timeline) from any other point.
697+
698+
// Is there some overlap here with Range?
699+
700+
### Processing Content States in Scopes: reset
701+
702+
// This may not be what we have discussed...
703+
704+
When a Content State is applied to a Container such as a Scene, it is assumed to be a "diff" - for example if 3 cameras and 4 lights are already present in the Scene, and a Content State asserts a single new Camera, the default behavior is to add this fourth Camera to the Scene and leave the existing resources as they are.
705+
706+
The client should reset the Container to its original state before applying the diff operation. However, for narratives that cumulatively build a Scene this may lead to excessively verbose Manifests. When moving through the items of an Annotation page with the behavior `sequence`, the Container is not reset and the diff is cumulative; modifications from one `scope` persist into the next. If this behavior is not wanted, the `reset` property of the content state annotation should be set to `true`:
707+
708+
```json
709+
{
710+
"type": "Annotation",
711+
"motivation": ["contentState"],
712+
"reset": true
713+
}
714+
```
715+
716+
Before applying the content state to the Scene, the client should reset the Scene to its original state as provided by the Manifest.
717+
718+
// I am assuming reset is always true except in `sequence` - otherwise it's completely unpredictable!! or is it... arbitrary navigation, state provided by initialization content states, etc...
719+
720+
### Contribute additional information permanently
721+
722+
Rerum inbox scenario - should be covered in CS2 protocol
723+
724+
### activating
725+
726+
Extension of hotspot linking
727+
728+
An annotation with the motivation `activating` can also carry a Content State in its body.
729+
730+
There are two uses of the `activating` annotation:
731+
732+
- triggering a content state
733+
- triggering a named animation
376734

377-
(not in section 6)
378735

379736
### reset
380737

381-
"diff", "original state" etc
738+
See above...
382739

740+
"diff", "original state" etc
383741
behavior for "force-order"?
384742
behavior: sequence
385743

0 commit comments

Comments
 (0)