Code Monkey home page Code Monkey logo

omeka-s-module-iiifserver's Introduction

IIIF Server (module for Omeka S)

New versions of this module and support for Omeka S version 3.0 and above are available on GitLab, which seems to respect users and privacy better than the previous repository.

Build Status

IIIF Server is a module for Omeka S that integrates the IIIF specifications to allow to process and share instantly images of any size and medias (pdf, audio, video, 3D…) in the desired formats. It can use any image server to display images and media, like the module Image Server, but you can use any other external one, like Cantaloupe or IIP Image.

The full specifications of the International Image Interoperability Framework standard are supported (service 2 or 3, level 2), so any widget that supports it can use it. Rotation, zoom, inside search, text overlay, etc. may be managed too. Dynamic lists of records may be created, for example for browse pages.

The IIIF manifests can be displayed with many viewers, the integrated OpenSeadragon, the Universal Viewer, the advanced Mirador, or the lighter and themable Diva, or any other IIIF compatible viewer.

The search is provided by the module Iiif Search for common xml formats.

Installation

Module

See general end user documentation for installing a module.

The module Common must be installed first.

The module uses external libraries, so use the release zip to install it, or use and init the source.

  • From the zip

Download the last release IiifServer.zip from the list of releases (the master does not contain the dependency), and uncompress it in the modules directory.

  • From the source and for development

If the module was installed from the source, rename the name of the folder of the module to IiifServer, go to the root of the module, and run:

composer install --no-dev

Then install it like any other Omeka module.

Note: To keep old options from Universal Viewer, upgrade it to version 3.4.3 before enabling of IiifServer. Else, simply set them in the config form.

PHP

PHP should be installed with the extension exif in order to get the size of images. This is the case for all major distributions and providers. At least one of the php extensions GD or Imagick are recommended. They are installed by default in most servers. If not, the image server will use the command line ImageMagick tool convert automatically.

Web server and identifiers containing /

This point is related to Apache. If you are using nginx, you can skip it.

If you are using Ark as identifier for items and IIIF manifests (through the modules Clean Url and optionally Ark), or any other identifier that contains a forward slash /, you must modify the Apache system configuration, because by default, it doesn't allow the url encoded / (%2F) inside urls for an old security issue.

Indeed, an Ark identifier contains at least two forward slashes / (ark:/12345/bNw3sx) and the IIIF specification requires to use url encoded slashes, except for the colon : (ark:%2F12345%2FbNw3sx). More precisely, this iiif requirement is specified in the Image Api, not in the presentation Api, but the identifiers are used in the same way.

AllowEncodedSlashes NoDecode

If you cannot access to config of the server, two settings can fix it in the config of the module :

  • disable the advanced option "Use the identifiers from Clean Url";
  • set the "Prefix to use for identifier".

CORS (Cross-Origin Resource Sharing)

To be able to share manifests and contents with other IIIF servers, the server should allow CORS. This feature can be enable in the config of the module, in the config of the server or in the file .htaccess.

Warning: the cors headers should be set one time only. If it is set multiple times, it will be disabled. This is the purpose of the option in the main config of the module.

If you prefer to append cors via the config the server, disable the option in the config first. On Apache 2.4, the module "headers" should be enabled:

a2enmod headers
systemctl restart apache2

Then, you have to add the following rules, adapted to your needs, to the file .htaccess at the root of Omeka S or in the main config of the server:

# CORS access for some files.
<IfModule mod_headers.c>
    Header setIfEmpty Access-Control-Allow-Origin "*"
    Header setIfEmpty Access-Control-Allow-Headers "origin, x-requested-with, content-type"
    Header setIfEmpty Access-Control-Allow-Methods "GET, POST"
</IfModule>

It is recommended to use the main config of the server, for example with the directive <Directory>.

To fix Amazon cors issues, see the aws documentation.

Cache

When your documents are big (more than 100 to 1000 pages, depending on your server, your network and your public), you may want to cache manifests in order to delivrate them instantly. In that case, check the option in the config.

Local access to iiif source

The iiif authentication api is not yet integrated. Anyway, to access iiif resources when authenticated, the fix #omeka/omeka-s/1714 can be patched or the module Guest can be used.

IIIF button in a theme

A resource page block is available in the theme settings. Else, you can add the view helper in your theme:

<?= $this->iiifManifestLink($item) ?>

Image server

Except if all your manifests are external or if you have no media, you will need a IIIF image server. It can be the module Image Server or an external server, like Cantaloupe or IIP Image. The image server may be used to display audio and video files too, if it supports them, else they will be served by Omeka.

Module Image Server

The module Image Server serves original images and can create tile statically or dynamically. This is the simplest way to get instant big images with Omeka. The images are the original ones, stored by Omeka.

External images servers

For other image servers, two configurations are possible.

Use the Omeka media type "IIIF Image"

The first possibility is to use an external server with a specific url path or a subdomain. In that case, you have to create or import all your images as media "IIIF Image". With this media type, the full json is saved in metadata of the media itself and the original images remain separate from Omeka.

This is the simplest when your images are already managed by one or multiple dedicated third-party image server (for instance one of the software listed in the official list of the IIIF community).

Of course, it requires a second tool to manage your images, at least to copy your directories of images in the image server (generally by ftp or a shared disk space).

Use original files as storage for the image server

The second possibility is to use the original images, so the files inside the directory "files/original". In that cases, the original files are managed by Omeka with the media types "Upload" or "Url". This possibility requires that the image server to be on the same server than Omeka, or at least that the image server can access the original directory via the file system of via http, or any another protocol.

Three params should be set:

  • set the original directory as the base path in your image server (option "FilesystemSource.BasicLookupStrategy.path_prefix" for Cantaloupe);
  • set the option "filename with extension" in the config of the module.
  • add some rules in Apache config or in htaccess to redirect request to the image server. Normally, a regex starting with iiif/ and finishing with the supported file extensions is enough.

Note for Cantaloupe

In some cases or if not configured, Image Api v3 does not work and images are not displayed, so keep Image Api v2 in that case.

Notes

The module allows to manage collections (item set level/item list), and manifests (item level). The info.json (media level) are managed by the image server.

Using externally supplied IIIF manifest

If you are harvesting data (via OAI-PMH, for instance) from another system where images are hosted and exposed via IIIF, you can use a configurable metadata field to supply the manifest to the viewer (Universal Viewer, Mirador or Diva). In this case, no images are hosted in the Omeka record, but one of the metadata fields has the URL of the manifest hosted on another server.

For example, you could set the alternative manifest element to "Dublin Core:Has Format" in the module configuration, and then put a URL like "https://example.com/iiif/HI-SK20161207-0009/manifest" in the specified element of a record. The viewer included on that record’s display page will use that manifest URL to retrieve images and metadata for the viewer.

Config options for manifest

Incompatible data

Some extracted texts produce invalid unicode / utf-8 data, so it is recommended to exclude the ocr data from the manifest. Anyway, it should not be included to follow the iiif specifications: the metadata are only used to display basic data about the document.

On new install, these properties are not included: dcterms:tableOfContents, bibo:content and extracttext:extracted_text. You may have to add them to avoid future issues.

Text overlay

For the overlay, only alto xml files are supported currently. They are automatically included in the manifest.

To enable it, you may check config of the viewer, for example add plugin "overlay" in the site setting of Mirador.

The alto xml files should be attached to the item as a media for now and it should have the same source filename than the image (except extension).

A future version will allow to use a linked media or a uri via a property.

A full example of iiif manifest with search, autocomplete and overlay can be found in the Wellcome library.

Input format of the property for structures (table of contents)

IIIF allows to display structures of documents.

The default structure is the simple sequential list of iiif medias.

To build structures for a complex document with a table of contents, you can use a specific property and fill a value with the needed json, or with a literal value with the following format. Each row is a part of the structure:

{id}, {label}, {canvasIndexOrRangeId1}; {canvasIndexOrRangeId2}; …; {canvasIndexOrRangeIdN}

Example:

cover, Front Cover, 1
r2, Introduction, 2; 3; 4; 5
backCover, Back Cover, 6

A new format allows to include the view number in the third column:

cover, Front Cover, 1, 1
r2, Introduction, 2, 2; 3; 4; 5
backCover, Back Cover, 6, 6

The range id (first part of a row) is the name of the range, that will be used to create the uri. To avoid collision with other indexes, it must not be a numeric value. It should be a simple alphanumeric name, without space, diacritic or any other special character, so it will be stable among all coding standards. It must not contain characters :/?&#%=<>;,. Ideally, the url-encoded id should be the same than the id. Anyway, this name is url-encoded in the final uri.

Furthermore, the range ids must be unique in all the item.

It can be skipped, so the line number will be used. In that case, keep the first comma to indicate that there is no specific range name. For example if r2 was not provided above, the internal range id will be r2 anyway, so r for range and 2 for second line. Nevertheless, this possibility is not recommended because the uri will change when a new line will be inserted.

The second part of the row is the label of the range, for example the title of the chapter. If empty, it will be used for the structure, but not displayed in the table of the viewer.

The last part of the row is the list of the top canvases or top ranges that the current range contains, so generally a list of images and sub-sections.

In most of the cases, the canvas index is the media position. Only medias that are used in the iiif are enumerated, not the specific medias, like pdf, xml, etc. attached to the item, so take care of its value, that may be different from the Omeka internal position in the list of attached medias to an item. Other indexes will be managed as range indexes if they are in the list of the range ids (first part of the row). If not, it will be a canvas alphanumeric name.

The first range id of the first line is the root of the tree. There can be only one root in iiif v3, but multiple structures. So if there are multiple roots (see below), a main range is added with all the roots as main branches.

If you use a xml value with module DataType Rdf, the structure above will be composed of canvases (element c here):

<c id="cover" label="Front Cover" ranges="1"/>
<c id="r2" label="Introduction" ranges="2; 3; 4; 5"/>
<c id="backcover" label="Back Cover" ranges="6"/>

The ranges can be omitted anyway, since the xml structure itself provide it (see nested xml below).

So it is possible to build complex hierarchical table of contents from this literal value, even with such an incomplete example, that is automatically completed with pages that are not sections:

toc, Table of Contents, cover; intro; r1; r2; backcover
    cover, Front cover, cover
    intro, Introduction, 2-5
    r1, First chapter, 6; r1-1; r1-2; 12
        r1-1, First section, r1-1-1; r1-1-2; illustration1; illus2
            r1-1-1, First sub-section, 8-9
            r1-1-2, Second sub-section, 9-10
    r2, Second chapter, 13
    backcover, Back cover, "backcover"
illustration1, First illustration non paginated, illus1
illustration3, Third illustration non paginated, illus3

equivalent of this nested xml:

<c id="toc" label="Table of Contents">
    <c id="cover" label="Front cover"/>
    <c id="intro" label="Introduction" range="2-5"/>
    <c id="r1" label="First chapter" range="6; r1-1; r1-2; 12">
        <c id="r1-1" label="First section" range="r1-1-1; r1-1-2; illustration1; illus2">
            <c id="r1-1-1" label="First sub-section" range="8-9"/>
            <c id="r1-1-2" label="Second sub-section" range="9-10"/>
            <c id="illustration1" label="First illustration non paginated" range="illus1"/>
        </c>
    </c>
    <c id="r2" label="Second chapter" range="13"/>
    <c id="backcover" label="Back cover"/>
</c>
<c id="illustration3" label="Third illustration non paginated" range="illus3"/>

equivalent of this flat indented xml (not recommended and deprecated):

<c id="toc" label="Table of Contents" range="cover; intro; r1; r2; backcover"/>
    <c id="cover" label="Front cover" range="cover"/>
    <c id="intro" label="Introduction" range="2-5"/>
    <c id="r1" label="First chapter" range="6; r1-1; r1-2; 12"/>
        <c id="r1-1" label="First section" range="r1-1-1; r1-1-2; illustration1; illus2"/>
            <c id="r1-1-1" label="First sub-section" range="8-9"/>
            <c id="r1-1-2" label="Second sub-section" range="9-10"/>
    <c id="r2" label="Second chapter" range="13"/>
    <c id="backcover" label="Back cover" range="backcover"/>
<c id="illustration1" label="First illustration non paginated" range="illus1"/>
<c id="illustration3" label="Third illustration non paginated" range="illus3"/>

to this json output (iiif v2):

[
  {
    "@id": "https://example.org/iiif/book1/range/toc",
    "@type": "sc:Range",
    "label": "Table of Contents",
    "ranges": [
      {
        "@id": "https://example.org/iiif/book1/range/cover",
        "@type": "sc:Range",
        "label": "Front cover",
        "ranges": [
          {
            "@id": "https://example.org/iiif/book1/range/cover",
            "@type": "sc:Range",
            "label": "Front cover"
          }
        ]
      },
      {
        "@id": "https://example.org/iiif/book1/range/intro",
        "@type": "sc:Range",
        "label": "Introduction",
        "canvases": [
          "https://example.org/iiif/book1/canvas/p2",
          "https://example.org/iiif/book1/canvas/p3",
          "https://example.org/iiif/book1/canvas/p4",
          "https://example.org/iiif/book1/canvas/p5"
        ]
      },
      {
        "@id": "https://example.org/iiif/book1/range/r1",
        "@type": "sc:Range",
        "label": "First chapter",
        "members": [
          {
            "@id": "https://example.org/iiif/book1/canvas/p6",
            "@type": "sc:Canvas",
            "label": "[6]"
          },
          {
            "@id": "https://example.org/iiif/book1/range/r1-1",
            "@type": "sc:Range",
            "label": "First section",
            "members": [
              {
                "@id": "https://example.org/iiif/book1/range/r1-1-1",
                "@type": "sc:Range",
                "label": "First sub-section",
                "canvases": [
                  "https://example.org/iiif/book1/canvas/p8",
                  "https://example.org/iiif/book1/canvas/p9"
                ]
              },
              {
                "@id": "https://example.org/iiif/book1/range/r1-1-2",
                "@type": "sc:Range",
                "label": "Second sub-section",
                "canvases": [
                  "https://example.org/iiif/book1/canvas/p9",
                  "https://example.org/iiif/book1/canvas/p10"
                ]
              },
              {
                "@id": "https://example.org/iiif/book1/range/illustration1",
                "@type": "sc:Range",
                "label": "First illustration non paginated",
                "canvases": [
                  "https://example.org/iiif/book1/canvas/illus1"
                ]
              },
              {
                "@id": "https://example.org/iiif/book1/canvas/illus2",
                "@type": "sc:Canvas",
                "label": "illus2"
              }
            ]
          },
          {
            "@id": "https://example.org/iiif/book1/canvas/r1-2",
            "@type": "sc:Canvas",
            "label": "r1-2"
          },
          {
            "@id": "https://example.org/iiif/book1/canvas/p12",
            "@type": "sc:Canvas",
            "label": "[12]"
          }
        ]
      },
      {
        "@id": "https://example.org/iiif/book1/range/r2",
        "@type": "sc:Range",
        "label": "Second chapter",
        "canvases": [
          "https://example.org/iiif/book1/canvas/p13"
        ]
      },
      {
        "@id": "https://example.org/iiif/book1/range/backcover",
        "@type": "sc:Range",
        "label": "Back cover",
        "canvases": [
          "https://example.org/iiif/book1/canvas/backcover"
        ]
      }
    ]
  },
  {
    "@id": "https://example.org/iiif/book1/range/illustration3",
    "@type": "sc:Range",
    "label": "Third illustration non paginated",
    "canvases": [
      "https://example.org/iiif/book1/canvas/illus3"
    ]
  }
]

or to this json output (iiif v3), a little more verbose:

[
  {
    "id": "https://example.org/iiif/book1/range/rstructure1",
    "type": "Range",
    "label": { "none": [ "Content" ] },
    "items": [
      {
        "id": "https://example.org/iiif/book1/range/toc",
        "type": "Range",
        "label": { "none": [ "Table of Contents" ] },
        "items": [
          {
            "id": "https://example.org/iiif/book1/range/cover",
            "type": "Range",
            "label": { "none": [ "Front cover" ] },
            "items": [
              { "id": "https://example.org/iiif/book1/canvas/cover", "type": "Canvas" }
            ]
          },
          {
            "id": "https://example.org/iiif/book1/range/intro",
            "type": "Range",
            "label": { "none": [ "Introduction" ] },
            "items": [
              { "id": "https://example.org/iiif/book1/canvas/p2", "type": "Canvas" },
              { "id": "https://example.org/iiif/book1/canvas/p3", "type": "Canvas" },
              { "id": "https://example.org/iiif/book1/canvas/p4", "type": "Canvas" },
              { "id": "https://example.org/iiif/book1/canvas/p5", "type": "Canvas" }
            ]
          },
          {
            "id": "https://example.org/iiif/book1/range/r1",
            "type": "Range",
            "label": { "none": [ "First chapter" ] },
            "items": [
              { "id": "https://example.org/iiif/book1/canvas/p6", "type": "Canvas" },
              {
                "id": "https://example.org/iiif/book1/range/r1-1",
                "type": "Range",
                "label": { "none": [ "First section" ] },
                "items": [
                  {
                    "id": "https://example.org/iiif/book1/range/r1-1-1",
                    "type": "Range",
                    "label": { "none": [ "First sub-section" ] },
                    "items": [
                      { "id": "https://example.org/iiif/book1/canvas/p8", "type": "Canvas" },
                      { "id": "https://example.org/iiif/book1/canvas/p9", "type": "Canvas" }
                    ]
                  },
                  {
                    "id": "https://example.org/iiif/book1/range/r1-1-2",
                    "type": "Range",
                    "label": { "none": [ "Second sub-section" ] },
                    "items": [
                      { "id": "https://example.org/iiif/book1/canvas/p9", "type": "Canvas" },
                      { "id": "https://example.org/iiif/book1/canvas/p10", "type": "Canvas" }
                    ]
                  },
                  {
                    "id": "https://example.org/iiif/book1/range/illustration1",
                    "type": "Range",
                    "label": { "none": [ "First illustration non paginated" ] },
                    "items": [
                      { "id": "https://example.org/iiif/book1/canvas/illus1", "type": "Canvas" }
                    ]
                  },
                  { "id": "https://example.org/iiif/book1/canvas/illus2", "type": "Canvas" }
                ]
              },
              { "id": "https://example.org/iiif/book1/canvas/r1-2", "type": "Canvas" },
              { "id": "https://example.org/iiif/book1/canvas/p12", "type": "Canvas" }
            ]
          },
          {
            "id": "https://example.org/iiif/book1/range/r2",
            "type": "Range",
            "label": { "none": [ "Second chapter" ] },
            "items": [
              { "id": "https://example.org/iiif/book1/canvas/p13", "type": "Canvas" }
            ]
          },
          {
            "id": "https://example.org/iiif/book1/range/backcover",
            "type": "Range",
            "label": { "none": [ "Back cover" ] },
            "items": [
              { "id": "https://example.org/iiif/book1/canvas/backcover", "type": "Canvas" }
            ]
          }
        ]
      },
      {
        "id": "https://example.org/iiif/book1/range/illustration3",
        "type": "Range",
        "label": { "none": [ "Third illustration non paginated" ] },
        "items": [
          { "id": "https://example.org/iiif/book1/canvas/illus3", "type": "Canvas" }
        ]
      }
    ]
  }
]

Notes to understand the conversion and to fix issues from the literal data:

  • The named canvases may not be supported, so you may have to avoid them.
  • The indentation is not required, but it simplifies literal visualisation.
  • The lines must be ordered as a table of contents or as an index, so the parser can understand the structure.
  • Each line will be a range, even if it refers to a single canvas, because only ranges are displayed to the user. So the cover, the second chapter and the illustration are ranges with a single item that is a canvas.
  • There are some missing pages (not scanned or lost).
  • The names have some meanings ("r1-1-1"), but it's not needed.
  • The cover refers to itself, so it's a named canvas within a range. This is not possible for iiif v2, so wrap it with double quotes.
  • The backcover has a canvas wrapped by double quotes to force it to be a canvas.
  • The sub-sections share one page (9).
  • The index "r1-2" in the indexes of the first chapter is missing, so it is added as a named canvas.
  • The index "12" is a canvas, so it is added to the list, and, as a canvas, won't be displayed in the index of the viewer.
  • The "illustration1" has a named canvas, since "illus1" is not a range.
  • The index "illustration1" of the first section is a range, but it is missing from the ordered list below the first section. So it is added directly at the right place and removed from the end.
  • The illustration3 is not used as a range, so it is a root, so there is more than one root, so a range is added to wrap all the structure.

Take care of nested structures: items must not belong to themselves, else they will be managed as canvases.

Of course, if the literal structure is well formed, you don't have to consider these fixes.

Otherwise, in IIIF v3, multiple structures are appended when there are multiple values in the item. For example, in a newspaper, it's possible to have a structure by page like a common table of contents, and a structure by articles. Indeed, an article can be written on multiple and non-sequential pages, and a page can contain many articles, illustrations, ads, etc. When there are multiple structures, the names of the ranges should have the same meaning between each structure (for example the index "cover" should be the front cover in all structures), because their uri will be the same.

More info about structures for IIIF presentation 2.1 and IIIF presentation 3.0.

Customize data of manifests

The module creates manifests with all the metadata of each record. A lot of config options allows to define each part of them. If it's not enough, the event iiifserver.manifest can be used to modify the exposed data of a manifest for items, collections, collection lists (search results) and media (info.json). So, it is possible, for example, to modify the citation, to remove or to add some metadata or to change the thumbnail.

Note: with a collection list, the parameter resource is an array of resources.

All the combinations are possible: external manifest for items, iiif image for external medias, a local standard media file with module Image Server.

Routes and urls

All routes of the IIIF server are defined in config/module.config.php. They follow the recommandations of the IIIF specifications.

To view the json-ld manifests created for each resources of Omeka S, simply try these urls (replace :id by a true id):

By default, ids are the internal ids of Omeka S, but it is recommended to use your own single and permanent identifiers that don’t depend on an internal pointer in a database. The term Dublin Core Identifier is designed for that and a record can have multiple single identifiers. There are many possibilities: named number like in a library or a museum, isbn for books, or random id like with ark, noid, doi, etc. They can be displayed in the public url with the modules Ark and/or Clean Url.

3D models

3D models are not supported by the IIIF standard, that manages only images (IIIF v2), and audio and video files (IIIF v3). Nevertheless, it is possible to create manifests that follows the standard except the format of the file, like an extended version of the standard. Only the widget Universal Viewer supports it natively since version 2.3, via the three.js library. It is called "ixif".

The other viewers integrated via modules (Diva and Mirador) in Omeka don’t support 3D.

For more info about support of 3D models and possible other requirements, see the module Three JS Model viewer.

TODO / Bugs

  • Implements ArrayObject to all classes to simplify events.
  • Implements ArrayObject to all classes to simplify events for Iiif v2.
  • Use only arrays, not standard objects.
  • Type of manifest: Use a list of classes or templates to determine the 3D files.
  • Type of manifest: Include pdf as rendering.
  • Structure: Clarify names of canvases and referenced canvas in the table of contents and list of items.
  • Structure: Implements recursive ranges in structures for IIIF v2.
  • Structure: Normalize the format of the structure: csv? ini? yaml? xml? Provide an automatic upgrade too.
  • Structure: Convert structure v3 to v2 and vice-versa.
  • Structure: Fully support alphanumeric name for canvas id.
  • Structure: Support translation of structure (use the language of the value?).
  • Structure: Full support of named canvases.
  • Use the option "no storage" for url of a media for external server.
  • Manage url prefix.
  • When a item set contains non image items, the left panel with the index is displayed only when the first item contains an image (UV).
  • Job to update data of IIIF Image.
  • Create a way to cache big iiif manifests (useless for image info.json).
  • Always return a thumbnail in iiif v3.
  • Include thumbnails in canvas to avoid fetching info.json (so cache whole manifest).
  • Check if multiple roots is working for structures in iiif v3. (yes, as multiple structures).
  • Store dimensions on item/media save.
  • Create a plugin MediaData that will merge MediaDimension, ImageSize, and allows to get media type.
  • Clarify option for home page with "default site", that may not be a site of the item.
  • Podcast on iiif v2.

See module Image Server.

Warning

Use it at your own risk.

It’s always recommended to backup your files and your databases and to check your archives regularly so you can roll back if needed.

Troubleshooting

See online issues on the module issues page on GitLab.

License

This module is published under the CeCILL v2.1 license, compatible with GNU/GPL and approved by FSF and OSI.

In consideration of access to the source code and the rights to copy, modify and redistribute granted by the license, users are provided only with a limited warranty and the software’s author, the holder of the economic rights, and the successive licensors only have limited liability.

In this respect, the risks associated with loading, using, modifying and/or developing or reproducing the software by the user are brought to the user’s attention, given its Free Software status, which may make it complicated to use, with the result that its use is reserved for developers and experienced professionals having in-depth computer knowledge. Users are therefore encouraged to load and test the suitability of the software as regards their requirements in conditions enabling the security of their systems and/or data to be ensured and, more generally, to use and operate it in the same conditions of security.

This Agreement may be freely reproduced and published, provided it is not altered, and that no provisions are either added or removed herefrom.

Copyright

  • Copyright Daniel Berthereau, 2015-2024 (see Daniel-KM)
  • Copyright BibLibre, 2016-2017
  • Copyright Régis Robineau, 2019 (see [regisrob])
  • Copyright Satoru Nakamura, 2021 (see nakamura196)

First version of this plugin was built for the Bibliothèque patrimoniale of Mines ParisTech. This Omeka S module is a rewrite of the Universal Viewer plugin for Omeka by BibLibre with the same features. Next, it was , but separated into three modules: the IIIF server, the Image Server and the viewer Universal Viewer. This viewer integrates the tiler Zoomify that was used the plugin OpenLayers Zoom for Omeka Classic and another tiler to support the Deep Zoom Image tile format.

omeka-s-module-iiifserver's People

Contributors

briancrogers avatar daniel-km avatar edsilv avatar jajm avatar nakamura196 avatar regisrob avatar symac avatar thibaudglt avatar waltricejr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

omeka-s-module-iiifserver's Issues

Image quality/tiling

This is related to the last issue posted.
I can't seem to get a decent detailed image even when I use a big Tiff. I've tried multiple saving methods, pyramidal and not. What specifications should the image be?
Also, when I import using the tiler I see no image in the viewer, Mirador or Universal Viewer.

Stockage des manifestes IIIF

Dans le cadre de notre projet de bibliothèque numérique patrimoniale, nous utilisons le plugin IIIF Server. Nous avons réussi à l’installer et à le faire fonctionner. Nous pouvons sans problèmes afficher les manifestes de nos ouvrages numérisés, en utilisant les URL présentés dans le ReadMe. Nous aimerions avoir quelques précisions sur la génération de ces manifestes : sont-ils générés dynamiquement ou bien sont-ils stockés quelque part ? S’ils sont générés dynamiquement, est-il recommandé de les récupérer et de les stocker sur un serveur ? S’ils sont stockés quelque part, pouvez-vous nous indiquer où nous pouvons les trouver ?
Merci par avance pour vos réponses et votre aide !

Getid3 class not found

Hello,

If I upload an audio or video file and then try to access the manifest, I receive an error:

Error: Class 'JamesHeinrich\GetID3\Utils' not found in /var/www/html/modules/IiifServer/vendor/james-heinrich/getid3/src/GetID3.php:180

Failed to get image resolution

I'm setting up a new site and using IIFServer 3.5.16. I'm seeing this error message in my site logs and no image in the Mirador viewer:

Zend\View\Exception\RuntimeException: Failed to get image resolution: square/ed1bbe41415d0a22d2d13ce6d32774ddb3e2149d.jpg in /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/modules/IiifServer/src/View/Helper/ImageSize.php:42 Stack trace: #0 [internal function]: IiifServer\View\Helper\ImageSize->__invoke(Object(Omeka\Api\Representation\MediaRepresentation), 'square') #1 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/vendor/zendframework/zend-view/src/Renderer/PhpRenderer.php(397): call_user_func_array(Object(IiifServer\View\Helper\ImageSize), Array) #2 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/modules/IiifServer/src/View/Helper/IiifManifest.php(606): Zend\View\Renderer\PhpRenderer->__call('imageSize', Array) #3 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/modules/IiifServer/src/View/Helper/IiifManifest.php(752): IiifServer\View\Helper\IiifManifest->_iiifThumbnail(Object(Omeka\Api\Representation\MediaRepresentation)) #4 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/modules/IiifServer/src/View/Helper/IiifManifest.php(287): IiifServer\View\Helper\IiifManifest->_iiifCanvasImage(Object(Omeka\Api\Representation\MediaRepresentation), 1) #5 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/modules/IiifServer/src/View/Helper/IiifManifest.php(72): IiifServer\View\Helper\IiifManifest->buildManifestItem(Object(Omeka\Api\Representation\ItemRepresentation)) #6 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/modules/IiifServer/src/Controller/PresentationController.php(156): IiifServer\View\Helper\IiifManifest->__invoke(Object(Omeka\Api\Representation\ItemRepresentation)) #7 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/vendor/zendframework/zend-mvc/src/Controller/AbstractActionController.php(78): IiifServer\Controller\PresentationController->itemAction() #8 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/vendor/zendframework/zend-eventmanager/src/EventManager.php(322): Zend\Mvc\Controller\AbstractActionController->onDispatch(Object(Zend\Mvc\MvcEvent)) #9 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/vendor/zendframework/zend-eventmanager/src/EventManager.php(179): Zend\EventManager\EventManager->triggerListeners(Object(Zend\Mvc\MvcEvent), Object(Closure)) #10 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/vendor/zendframework/zend-mvc/src/Controller/AbstractController.php(106): Zend\EventManager\EventManager->triggerEventUntil(Object(Closure), Object(Zend\Mvc\MvcEvent)) #11 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/vendor/zendframework/zend-mvc/src/DispatchListener.php(138): Zend\Mvc\Controller\AbstractController->dispatch(Object(Zend\Http\PhpEnvironment\Request), Object(Zend\Http\PhpEnvironment\Response)) #12 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/vendor/zendframework/zend-eventmanager/src/EventManager.php(322): Zend\Mvc\DispatchListener->onDispatch(Object(Zend\Mvc\MvcEvent)) #13 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/vendor/zendframework/zend-eventmanager/src/EventManager.php(179): Zend\EventManager\EventManager->triggerListeners(Object(Zend\Mvc\MvcEvent), Object(Closure)) #14 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/vendor/zendframework/zend-mvc/src/Application.php(332): Zend\EventManager\EventManager->triggerEventUntil(Object(Closure), Object(Zend\Mvc\MvcEvent)) #15 /Users/scottmetoyer/src/ucr-library-omeka-s/omekas/index.php(21): Zend\Mvc\Application->run() #16 {main}

Any idea what I'm missing?

Failed opening required 'modules/IiifServer/vendor/autoload.php'

Chez moi, l'installation de la version git master de ce module échoue :

Warning: require_once(/...//modules/IiifServer/vendor/autoload.php): failed to open stream: No such file or directory in /...//modules/IiifServer/Module.php on line 50

Fatal error: require_once(): Failed opening required '/...//modules/IiifServer/vendor/autoload.php' (include_path='.:/shared/php/7.0/7.0.32/lib/php') in /...//modules/IiifServer/Module.php on line 50

REGEXP error

We're seeing the following error in the latest version of IIIF Server (3.6.6.3) and Omeka (3.1.1). Any idea what we're doing wrong?

`Doctrine\DBAL\Exception\DriverException
An exception occurred while executing 'SELECT id FROM media media WHERE (item_id = ?) AND (has_thumbnails = 1) AND (media_type IN ("image/jpeg", "image/png", "image/gif", "image/webp")) AND ((source IN ( "thumb.jpg", "thumbnail.jpg", "screenshot.jpg", "vignette.jpg", "miniatura.jpg", "thumb.jpeg", "thumbnail.jpeg", "screenshot.jpeg", "vignette.jpeg", "miniatura.jpeg", "thumb.png", "thumbnail.png", "screenshot.png", "vignette.png", "miniatura.png", "thumb.gif", "thumbnail.gif", "screenshot.gif", "vignette.gif", "miniatura.gif", "thumb.webp", "thumbnail.webp", "screenshot.webp", "vignette.webp", "miniatura.webp" )) OR (source REGEXP "/(?:thumb|thumbnail|screenshot|vignette|miniatura).(?:jpg|jpeg|png|gif|webp)$")) ORDER BY id ASC LIMIT 1' with params [1111]: SQLSTATE[42000]: Syntax error or access violation: 1139 Got error 'repetition-operator operand invalid' from regexp

Details:

PDOException: SQLSTATE[42000]: Syntax error or access violation: 1139 Got error 'repetition-operator operand invalid' from regexp in /var/app/current/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:112
Stack trace:
#0 /var/app/current/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php(112): PDOStatement->execute(NULL)
#1 /var/app/current/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(1292): Doctrine\DBAL\Driver\PDOStatement->execute()
#2 /var/app/current/modules/IiifServer/src/View/Helper/IiifManifest2.php(1452): Doctrine\DBAL\Connection->executeQuery('SELECT id FROM ...', Array)
#3 /var/app/current/modules/IiifServer/src/View/Helper/IiifManifest2.php(296): IiifServer\View\Helper\IiifManifest2->_mainThumbnail(Object(Omeka\Api\Representation\ItemRepresentation), true)
#4 /var/app/current/modules/IiifServer/src/View/Helper/IiifManifest2.php(95): IiifServer\View\Helper\IiifManifest2->buildManifestItem(Object(Omeka\Api\Representation\ItemRepresentation))
#5 [internal function]: IiifServer\View\Helper\IiifManifest2->__invoke(Object(Omeka\Api\Representation\ItemRepresentation))
#6 /var/app/current/vendor/laminas/laminas-view/src/Renderer/PhpRenderer.php(396): call_user_func_array(Object(IiifServer\View\Helper\IiifManifest2), Array)
#7 /var/app/current/modules/IiifServer/src/View/Helper/IiifManifest.php(59): Laminas\View\Renderer\PhpRenderer->__call('iiifManifest2', Array)
#8 /var/app/current/modules/IiifServer/src/Controller/PresentationController.php(110): IiifServer\View\Helper\IiifManifest->__invoke(Object(Omeka\Api\Representation\ItemRepresentation), '2')
#9 /var/app/current/vendor/laminas/laminas-mvc/src/Controller/AbstractActionController.php(77): IiifServer\Controller\PresentationController->manifestAction()
#10 /var/app/current/vendor/laminas/laminas-eventmanager/src/EventManager.php(321): Laminas\Mvc\Controller\AbstractActionController->onDispatch(Object(Laminas\Mvc\MvcEvent))
#11 /var/app/current/vendor/laminas/laminas-eventmanager/src/EventManager.php(178): Laminas\EventManager\EventManager->triggerListeners(Object(Laminas\Mvc\MvcEvent), Object(Closure))
#12 /var/app/current/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php(103): Laminas\EventManager\EventManager->triggerEventUntil(Object(Closure), Object(Laminas\Mvc\MvcEvent))
#13 /var/app/current/vendor/laminas/laminas-mvc/src/DispatchListener.php(139): Laminas\Mvc\Controller\AbstractController->dispatch(Object(Laminas\Http\PhpEnvironment\Request), Object(Laminas\Http\PhpEnvironment\Response))
#14 /var/app/current/vendor/laminas/laminas-eventmanager/src/EventManager.php(321): Laminas\Mvc\DispatchListener->onDispatch(Object(Laminas\Mvc\MvcEvent))
#15 /var/app/current/vendor/laminas/laminas-eventmanager/src/EventManager.php(178): Laminas\EventManager\EventManager->triggerListeners(Object(Laminas\Mvc\MvcEvent), Object(Closure))
#16 /var/app/current/vendor/laminas/laminas-mvc/src/Application.php(331): Laminas\EventManager\EventManager->triggerEventUntil(Object(Closure), Object(Laminas\Mvc\MvcEvent))
#17 /var/app/current/index.php(21): Laminas\Mvc\Application->run()
#18 {main}

Next Doctrine\DBAL\Driver\PDO\Exception: SQLSTATE[42000]: Syntax error or access violation: 1139 Got error 'repetition-operator operand invalid' from regexp in /var/app/current/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDO/Exception.php:18
Stack trace:
#0 /var/app/current/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php(114): Doctrine\DBAL\Driver\PDO\Exception::new(Object(PDOException))
#1 /var/app/current/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(1292): Doctrine\DBAL\Driver\PDOStatement->execute()
#2 /var/app/current/modules/IiifServer/src/View/Helper/IiifManifest2.php(1452): Doctrine\DBAL\Connection->executeQuery('SELECT id FROM ...', Array)
#3 /var/app/current/modules/IiifServer/src/View/Helper/IiifManifest2.php(296): IiifServer\View\Helper\IiifManifest2->_mainThumbnail(Object(Omeka\Api\Representation\ItemRepresentation), true)
#4 /var/app/current/modules/IiifServer/src/View/Helper/IiifManifest2.php(95): IiifServer\View\Helper\IiifManifest2->buildManifestItem(Object(Omeka\Api\Representation\ItemRepresentation))
#5 [internal function]: IiifServer\View\Helper\IiifManifest2->__invoke(Object(Omeka\Api\Representation\ItemRepresentation))
#6 /var/app/current/vendor/laminas/laminas-view/src/Renderer/PhpRenderer.php(396): call_user_func_array(Object(IiifServer\View\Helper\IiifManifest2), Array)
#7 /var/app/current/modules/IiifServer/src/View/Helper/IiifManifest.php(59): Laminas\View\Renderer\PhpRenderer->__call('iiifManifest2', Array)
#8 /var/app/current/modules/IiifServer/src/Controller/PresentationController.php(110): IiifServer\View\Helper\IiifManifest->__invoke(Object(Omeka\Api\Representation\ItemRepresentation), '2')
#9 /var/app/current/vendor/laminas/laminas-mvc/src/Controller/AbstractActionController.php(77): IiifServer\Controller\PresentationController->manifestAction()
#10 /var/app/current/vendor/laminas/laminas-eventmanager/src/EventManager.php(321): Laminas\Mvc\Controller\AbstractActionController->onDispatch(Object(Laminas\Mvc\MvcEvent))
#11 /var/app/current/vendor/laminas/laminas-eventmanager/src/EventManager.php(178): Laminas\EventManager\EventManager->triggerListeners(Object(Laminas\Mvc\MvcEvent), Object(Closure))
#12 /var/app/current/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php(103): Laminas\EventManager\EventManager->triggerEventUntil(Object(Closure), Object(Laminas\Mvc\MvcEvent))
#13 /var/app/current/vendor/laminas/laminas-mvc/src/DispatchListener.php(139): Laminas\Mvc\Controller\AbstractController->dispatch(Object(Laminas\Http\PhpEnvironment\Request), Object(Laminas\Http\PhpEnvironment\Response))
#14 /var/app/current/vendor/laminas/laminas-eventmanager/src/EventManager.php(321): Laminas\Mvc\DispatchListener->onDispatch(Object(Laminas\Mvc\MvcEvent))
#15 /var/app/current/vendor/laminas/laminas-eventmanager/src/EventManager.php(178): Laminas\EventManager\EventManager->triggerListeners(Object(Laminas\Mvc\MvcEvent), Object(Closure))
#16 /var/app/current/vendor/laminas/laminas-mvc/src/Application.php(331): Laminas\EventManager\EventManager->triggerEventUntil(Object(Closure), Object(Laminas\Mvc\MvcEvent))
#17 /var/app/current/index.php(21): Laminas\Mvc\Application->run()
#18 {main}

Next Doctrine\DBAL\Exception\DriverException: An exception occurred while executing 'SELECT id FROM media media WHERE (item_id = ?) AND (has_thumbnails = 1) AND (media_type IN ("image/jpeg", "image/png", "image/gif", "image/webp")) AND ((source IN (
"thumb.jpg", "thumbnail.jpg", "screenshot.jpg", "vignette.jpg", "miniatura.jpg",
"thumb.jpeg", "thumbnail.jpeg", "screenshot.jpeg", "vignette.jpeg", "miniatura.jpeg",
"thumb.png", "thumbnail.png", "screenshot.png", "vignette.png", "miniatura.png",
"thumb.gif", "thumbnail.gif", "screenshot.gif", "vignette.gif", "miniatura.gif",
"thumb.webp", "thumbnail.webp", "screenshot.webp", "vignette.webp", "miniatura.webp"
)) OR (source REGEXP "/(?:thumb|thumbnail|screenshot|vignette|miniatura).(?:jpg|jpeg|png|gif|webp)$")) ORDER BY id ASC LIMIT 1' with params [1111]:

SQLSTATE[42000]: Syntax error or access violation: 1139 Got error 'repetition-operator operand invalid' from regexp in /var/app/current/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php:128
Stack trace:
#0 /var/app/current/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php(182): Doctrine\DBAL\Driver\AbstractMySQLDriver->convertException('An exception oc...', Object(Doctrine\DBAL\Driver\PDO\Exception))
#1 /var/app/current/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php(159): Doctrine\DBAL\DBALException::wrapException(Object(Doctrine\DBAL\Driver\PDO\MySQL\Driver), Object(Doctrine\DBAL\Driver\PDO\Exception), 'An exception oc...')
#2 /var/app/current/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(2214): Doctrine\DBAL\DBALException::driverExceptionDuringQuery(Object(Doctrine\DBAL\Driver\PDO\MySQL\Driver), Object(Doctrine\DBAL\Driver\PDO\Exception), 'SELECT id FROM ...', Array)
#3 /var/app/current/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php(1301): Doctrine\DBAL\Connection->handleExceptionDuringQuery(Object(Doctrine\DBAL\Driver\PDO\Exception), 'SELECT id FROM ...', Array, Array)
#4 /var/app/current/modules/IiifServer/src/View/Helper/IiifManifest2.php(1452): Doctrine\DBAL\Connection->executeQuery('SELECT id FROM ...', Array)
#5 /var/app/current/modules/IiifServer/src/View/Helper/IiifManifest2.php(296): IiifServer\View\Helper\IiifManifest2->_mainThumbnail(Object(Omeka\Api\Representation\ItemRepresentation), true)
#6 /var/app/current/modules/IiifServer/src/View/Helper/IiifManifest2.php(95): IiifServer\View\Helper\IiifManifest2->buildManifestItem(Object(Omeka\Api\Representation\ItemRepresentation))
#7 [internal function]: IiifServer\View\Helper\IiifManifest2->__invoke(Object(Omeka\Api\Representation\ItemRepresentation))
#8 /var/app/current/vendor/laminas/laminas-view/src/Renderer/PhpRenderer.php(396): call_user_func_array(Object(IiifServer\View\Helper\IiifManifest2), Array)
#9 /var/app/current/modules/IiifServer/src/View/Helper/IiifManifest.php(59): Laminas\View\Renderer\PhpRenderer->__call('iiifManifest2', Array)
#10 /var/app/current/modules/IiifServer/src/Controller/PresentationController.php(110): IiifServer\View\Helper\IiifManifest->__invoke(Object(Omeka\Api\Representation\ItemRepresentation), '2')
#11 /var/app/current/vendor/laminas/laminas-mvc/src/Controller/AbstractActionController.php(77): IiifServer\Controller\PresentationController->manifestAction()
#12 /var/app/current/vendor/laminas/laminas-eventmanager/src/EventManager.php(321): Laminas\Mvc\Controller\AbstractActionController->onDispatch(Object(Laminas\Mvc\MvcEvent))
#13 /var/app/current/vendor/laminas/laminas-eventmanager/src/EventManager.php(178): Laminas\EventManager\EventManager->triggerListeners(Object(Laminas\Mvc\MvcEvent), Object(Closure))
#14 /var/app/current/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php(103): Laminas\EventManager\EventManager->triggerEventUntil(Object(Closure), Object(Laminas\Mvc\MvcEvent))
#15 /var/app/current/vendor/laminas/laminas-mvc/src/DispatchListener.php(139): Laminas\Mvc\Controller\AbstractController->dispatch(Object(Laminas\Http\PhpEnvironment\Request), Object(Laminas\Http\PhpEnvironment\Response))
#16 /var/app/current/vendor/laminas/laminas-eventmanager/src/EventManager.php(321): Laminas\Mvc\DispatchListener->onDispatch(Object(Laminas\Mvc\MvcEvent))
#17 /var/app/current/vendor/laminas/laminas-eventmanager/src/EventManager.php(178): Laminas\EventManager\EventManager->triggerListeners(Object(Laminas\Mvc\MvcEvent), Object(Closure))
#18 /var/app/current/vendor/laminas/laminas-mvc/src/Application.php(331): Laminas\EventManager\EventManager->triggerEventUntil(Object(Closure), Object(Laminas\Mvc\MvcEvent))
#19 /var/app/current/index.php(21): Laminas\Mvc\Application->run()
#20 {main}`

Empty array in profile of info.js

In the info.json generated by the IIIF Server module (version 3.6.6. / Omeka S version 3.2.2) there's an empty array in the profile part.
For example:

{
  "@context": "http://iiif.io/api/image/2/context.json",
  "@id": "https://www.goudatijdmachine.nl/data/iiif/2/51803",
  "protocol": "http://iiif.io/api/image",
  "width": 10290,
  "height": 8664,
  "sizes": [
    {
      "width": 200,
      "height": 168
    },
    {
      "width": 800,
      "height": 674
    },
    {
      "width": 10290,
      "height": 8664
    }
  ],
  "profile": [
    "http://iiif.io/api/image/2/level2.json",
    []
  ]
}

The source code https://github.com/Daniel-KM/Omeka-S-module-IiifServer/blob/master/src/View/Helper/IiifInfo2.php#L107 mentions the empy array as a temporary fix for UniversalViewer/universalviewer#438 (dated 2017).

I wonder if this temporary fix is still needed. Some parsers throw an error because of this empty array... I commented out the line which added the empty array and everything still works and the parser of the tool I used could handle the info.js now without problems.

`add` statements for CORS header creates syntax error

Hello,
I'm very new in IIIF,
I just installed IIIF server and image server in my omek-Sv4 instance.
It seems to work fine locally:

BUT
when I try to use the manifest elsewhere on the web, I allways get error.
example

None of them are reading my manifests.
but they succeed in reading other manifests I found on the web.

Is there anything I did wrong? Maybe something with CORS.
I have these lines:

<Directory "_directory_">
    Options FollowSymLinks
    AllowOverrides All
    Require all granted
    <IfModule mod_headers.c>
        Header setIfEmpty Access-Control-Allow-Origin "*"
        Header setIfEmpty Access-Control-Allow-Headers "origin, x-requested-with, content-type"
        Header setIfEmpty Access-Control-Allow-Methods "GET, POST"
    </IfModule>
</Directory>

in my /etc/apache2/available-site (which is enabled and in use)

It may also be the proxies of the virtual machine hosting service creating restrictions in CORS.
But I don't know how to ask/debug this since I have no log for the errors...

Thanks for you help

Missing required keys for iiif resource type "Manifest": "items"

I added media to an item via the "IIIF image" option, this works well as you see via JSON-LD of the item).
But when I request the IIIF Manifest v3 of this item I get:

{
  status: "error",
  message: "Item #134190: Missing required keys for iiif resource type "Manifest": "items"."
}

Note 1:The IIIF Manifest v2 of this item looks alright.
Note 2: when I upload an image, the IIIF Manifest v2 and v3 look alright.

Running IIIF Server version 3.6.14 on Omeka S version 4.0.1.

Item manifest: Empty href in descriptive metadata link in

IiifServer version 3.5.16 - Option 'Link for descriptive metadata' enabled

When an item has a value referencing another item, the resulting metadata in the IIIF manifest contains an empty link (empty href):

{ label: "Source", value: "<a class="resource-link" href=""><span class="resource-name">Punch, or the London Charivari</span></a>" }

I fixed this by altering function 'valuesAsHtml' in 'scr/View/Helper/IiifManifest.php':

old:

if ($v->type() === 'resource') {
$r = $v->valueResource();

new:

if ( ( $v->type() === 'resource' || $v->type() === 'resource:item' ) && $r = $v->valueResource() ) {

External image server

Hello,

I'm having a bit of a hard time trying to use this with an external image server. I'm guessing I would put the url of the server in the IIIF Image base url field? But then how would I identify specific images on the image server in the Omeka record.

Apologies if I'm misunderstanding this functionality.

-Joseph Anderson

Invalid IIIF image service in NuBIS Manifest

Not completely sure it is related to this module or the ImageServer module, or both, but there is a compatibility issue in the image service of canvases in NuBIS's manifests:
https://nubis.univ-paris1.fr/iiif/ark:/15733/mr4p/manifest
https://nubis.univ-paris1.fr/iiif/ark:/15733/1t2h/manifest

The values of resource.service['@context'] and resource.service.profile are not valid: it is 2, instead of the full URIs recommended by the IIIF Image API spec.

This can be a major issue for IIIF viewers, and prevent from using a manifest as a linked data document serialized in JSON-LD.

ping @AlyxTaj

Translation within Manifest is not working

I have a translation file to translate the string "Download as PDF" within the manifest. The call is made in the code at line 292 in the file modules/IiiifServer/srv/ViewHelper/IiifManifest2.php
However, the translation does not take effect. Why does IIIF server ignore the existing translation?

Non-visible or non public media are included in Manifest

Non-visible or non public media are included in manifest for an item. I quick fix it including conditional on foreach $medias loop:
(starting at line 213)
foreach ($medias as $media) { if($media->isPublic()){ ... } ....
Thumbnail generation is important, because can reveal hidden media. I fix changing query:

(original first line 1020)

$qb = $conn->createQueryBuilder() ->select('media.id') ->from('media', 'media') ->leftJoin('media','resource','resource', # \Doctrine\ORM\Query\Expr\Join::WITH, ?? 'media.id = resource.id' ) ->where('item_id = :item_id') ->setParameter(':item_id', $resource->id()) ->andWhere('has_thumbnails = 1') ->andWhere('resource.is_public = 1') ->orderBy('id', 'ASC') ->setMaxResults(1);

Mirador modules does not load image

My Omeka S site is the test site for our production site. It is a copy of both the code and the database but on two different servers. The Omeka S install uses iiif-server, iiif-presentation, image-server, Mirador Viewer and Amazon-S3. On S3, I use two different buckets with copies of the image files, one for production and one for test. The production site works fine.

However, on the test site, when I Browse items, I get a list of all the items with their thumbnails. When I select an item to load into Mirador, Mirador loads with no error messages but no image appears. In the info for the image, the URL for the manifest is https://website/iiif/3/10895/manifest.

In order to compare images, I have added a button that copies the manifest so that I can use the Add Resource in Mirador to add another window. The URL for the manifest uses the iiif-presentation format, https://website/iiif-presentation/3/item/10895/manifest. When I add this resource, the image shows up fine in Mirador. This is also true when I use the Mirador test site and add a resource. The manifest for the item shows nothing; the manifest for iiif-presentation shows the image.

So it doesn't seem like the retrieval of the image from S3 is a problem because I get both thumbnails and images with the correct URL. While the data in the manifest is structured differently, it does seem to contain the same info. I've tweaked everything I can think of with no changes. Any suggestions or ideas?

Will

License Property Configuration on module don't work

License property selected at module configuration is ignored (tested on version 3.5.14) . Default value is show in manifest everytime. I fixed quickly with this fast changes on Helper/IiifManifest.php

(starting at line 141)

       $licenseProperty = $this->view->setting('iiifserver_manifest_license_property');

        if ($licenseProperty) {
            $license = $item->value($licenseProperty);
	    	$license = strip_tags($license);
        }

La propriété IIIF "license" devrait pointer uniquement sur une URI

Même si l'API Présentation 2.1 n'indique pas explicitement un MUST, la propriété license est censée contenir uniquement une URI et non du texte (https://iiif.io/api/presentation/2.1/#license).
Tout mention textuelle concernant les questions de droits/licence est à mettre de préférence dans le propriété attribution (2.1), dans requiredStatement (3.0), voire dans un champ de metadata.

Manifest concerné : https://nubis.univ-paris1.fr/iiif/ark:/15733/1t2h/manifest (invalide, à cause de la mention "Licence Ouverte Etalab" dans license)

cc @AlyxTaj

since update to latest IiifServer (3.6.5.3), i get these errors , for example when universal viewer tries to retrieve a .json file. My omekas is at version 3.0.2

2021-08-17T10:11:20+00:00 ERR (3): Laminas\ServiceManager\Exception\ServiceNotFoundException: A plugin by the name "iiifImageUrl" was not found in the plugin manager Laminas\View\HelperPluginManager in /var/www/omeka-s/vendor/laminas/laminas-servicemanager/src/AbstractPluginManager.php:14
3
Stack trace:
#0 /var/www/omeka-s/vendor/laminas/laminas-view/src/Renderer/PhpRenderer.php(375): Laminas\ServiceManager\AbstractPluginManager->get()
#1 /var/www/omeka-s/vendor/laminas/laminas-view/src/Renderer/PhpRenderer.php(393): Laminas\View\Renderer\PhpRenderer->plugin()
#2 /var/www/omeka-s/modules/ImageServer/src/View/Helper/IiifInfo2.php(84): Laminas\View\Renderer\PhpRenderer->__call()
#3 [internal function]: ImageServer\View\Helper\IiifInfo2->__invoke()
#4 /var/www/omeka-s/vendor/laminas/laminas-view/src/Renderer/PhpRenderer.php(396): call_user_func_array()
#5 /var/www/omeka-s/modules/ImageServer/src/View/Helper/IiifInfo.php(65): Laminas\View\Renderer\PhpRenderer->__call()
#6 /var/www/omeka-s/modules/ImageServer/src/Controller/ImageController.php(134): ImageServer\View\Helper\IiifInfo->__invoke()
#7 /var/www/omeka-s/vendor/laminas/laminas-mvc/src/Controller/AbstractActionController.php(77): ImageServer\Controller\ImageController->infoAction()
#8 /var/www/omeka-s/vendor/laminas/laminas-eventmanager/src/EventManager.php(321): Laminas\Mvc\Controller\AbstractActionController->onDispatch()
#9 /var/www/omeka-s/vendor/laminas/laminas-eventmanager/src/EventManager.php(178): Laminas\EventManager\EventManager->triggerListeners()
#10 /var/www/omeka-s/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php(103): Laminas\EventManager\EventManager->triggerEventUntil()
#11 /var/www/omeka-s/vendor/laminas/laminas-mvc/src/DispatchListener.php(139): Laminas\Mvc\Controller\AbstractController->dispatch()
#12 /var/www/omeka-s/vendor/laminas/laminas-eventmanager/src/EventManager.php(321): Laminas\Mvc\DispatchListener->onDispatch()
#13 /var/www/omeka-s/vendor/laminas/laminas-eventmanager/src/EventManager.php(178): Laminas\EventManager\EventManager->triggerListeners()
#14 /var/www/omeka-s/vendor/laminas/laminas-mvc/src/Application.php(331): Laminas\EventManager\EventManager->triggerEventUntil()
#15 /var/www/omeka-s/index.php(21): Laminas\Mvc\Application->run()
#16 {mai

Problème d'affichage des images en taille réelle / problem retrieving full-size images

Bonjour

J'ai peur de mal exprimer en anglais les difficultés que je rencontre

Si je demande une image en taille réelle en prenant default comme paramètre de qualité,
/full/full/0/default.jpg
je constate une redirection vers l'url de l'image originale
files/original/7576501b26831957a9046ae88e165c33589f894e.jpg

ce qui n'est pas le cas avec color /full/full/0/color.jpg où l'url est conservé et le rendu correct

Ce comportement est celui constaté avec une image chargée simplement sur le serveur.

Les images que nous avons sont assez grosses, elles ont été importées sur le serveur via sideload et converties en tuiles via le script magick-slicer https://github.com/VoidVolker/MagickSlicer.

Je constate alors un autre dysfonctionnement dans le rendu des images en taille réelle. Le paramètre de région à full avec la qualité default renvoie une miniature après redirection. La redirection n'existe qu'avec la région à full.

Avec color j'ai le même problème, une vignette à la place de l'image entière, mais pas de redirection.

Par ailleurs, le rendu de ces images converties préalablement en tuiles ne semble pas fonctionner correctement, par exemple 0,0,500,500/600,230/0/default.jpg renvoie une vignette de 230px au carré après un très long temps de traitement

th

Time-out on manifest v3

When I load a manifest with 449 images via https://www.goudatijdmachine.nl/data/iiif/2/46491/manifest, this version 2 loads in about 3 seconds. But, when I load version 3 of the same manifest via https://www.goudatijdmachine.nl/data/iiif/3/46491/manifest I get an error:

Maximum execution time of 30 seconds exceeded

For your information:

IIIF image format in manifest

I’ve found some problems testing many different IIIF clients where some of them are not able to open some omeka media.
Going deep in that issues I’ve found that the problem depends on the format field value in the metadata of the media.
In fact I saw that when I load by Tiler a tif image instead of a jpeg, even if the tile version of the media is made by jpegs, the format stored in metada is “image/tiff” and this seems to be the reason why those clients fail.
If I force that format to image/jpeg, those IIIF clients work as a charm.
So I’m wondering if “image/tiff” is incorrect for those tile images coming from a master file in tiff format, and if the right image format for a tile image is always “image/jpeg” indipendently from the original master file format?

Question regarding "using externally supplied IIIF manifest"

Hello,

In your README, it suggests that you can load externally hosted presentation API manifests by setting the alternative manifest to a specific field like dcterms:hasFormat. I've done this, but something unexpected is happening.

To be specific, in Universal Viewer settings I've set the Manifest property to Dublin Core : Has Format.

I've then added an item with the following metadata:

Title: Test
Has Format: https://damsssl.llgc.org.uk/iiif/2.0/4389767/manifest.json

Then, in a page, I've added a Universal Viewer block with an attachment to my Test item above.

When I view the page, Universal Viewer displays, but the canvases don't. That's because it's loading this manifest:

https://tennessee.omeka.net/iiif/8/manifest

which loads this JSON:

{
	"@context": ["http://iiif.io/api/presentation/2/context.json", "http://wellcomelibrary.org/ld/ixif/0/context.json"],
	"@id": "https://tennessee.omeka.net/iiif/8/manifest",
	"@type": "sc:Manifest",
	"label": "Test",
	"license": "http://www.example.org/license.html",
	"attribution": "Provided by Example Organization",
	"related": {
		"@id": "https://tennessee.omeka.net/s/sample/item/8",
		"format": "text/html"
	},
	"seeAlso": {
		"@id": "https://tennessee.omeka.net/api/items/8",
		"format": "application/ld+json"
	},
	"metadata": [{
		"label": "Title",
		"value": "Test"
	}, {
		"label": "Has Format",
		"value": "https://damsssl.llgc.org.uk/iiif/2.0/4389767/manifest.json"
	}],
	"sequences": [{
		"@id": "https://tennessee.omeka.net/iiif/8/sequence/normal",
		"@type": "sc:Sequence",
		"label": "Unsupported extension. This manifest is being used as a wrapper for non-IIIF content (e.g., audio, video) and is unfortunately incompatible with IIIF viewers.",
		"compatibilityHint": "displayIfContentUnsupported",
		"canvases": [{
			"@id": "/iiif/ixif-message/canvas/c1",
			"@type": "sc:Canvas",
			"label": "Placeholder image",
			"thumbnail": "/modules/IiifServer/asset/img/thumbnails/placeholder-image.png?v=3.5.16",
			"width": 200,
			"height": 200,
			"images": [{
				"@id": "/iiif/ixif-message/imageanno/placeholder",
				"@type": "oa:Annotation",
				"motivation": "sc:painting",
				"resource": {
					"@id": "/iiif/ixif-message-0/res/placeholder",
					"@type": "dctypes:Image",
					"width": 200,
					"height": 200
				},
				"on": "/iiif/ixif-message/canvas/c1"
			}]
		}]
	}]
}

The metadata section with the Has Format key is pointing at the IIIF manifest I want to load in the viewer, but it's not loading the actual IIIF object that I want from that manifest. Have I misinterpreted how to add an object from an externally hosted IIIF presentation manifest?

Apologies if this question is a "dumb question." I'm brand new to Omeka and Omeka-S and trying to wrap my head around how we can use Omeka to tell stories using images from our external IIIF image server.

Tiler (not BulkTiler) failed to store Media object to DB.

Here I'm using IIIfServer 3.5.15 with Omeka S 2.1.0, and confirmed that the BulkTiler worked perfectly, but I failed to upload an image via Tiler.

What I did:
Edit an item, open the media tab, select 'Tiler' from the 'Add media' side menu, then choose a file and click the save button.

What I received:
It took for a while (probably the 30sec x 4 sleeps) and received an error report that said:

Omeka\Job\Exception\InvalidArgumentException: The media to tile cannot be identified. in /home/fukuchi/omeka-s/modules/IiifServer/src/Job/Tiler.php:16

Further details:
I found that an image file was uploaded to files/origin, and scaled images were also stored in large, medium and square.

I opened the database and posted the following query, but I could not find the newly uploaded media.

select id,storage_id from media;

The job that Tiler generated was found at the top of the job list, and its args ('storageId' and 'storagePath') seemed correct as far as checked.

From these observations, I guess that the system fails to store the new media object to the 'media' table, then getMediaIdViaSql() in IifServer/src/Job/Tiler.php failed to find the media.

Any suggestions and comments are welcome.

Question sur le README : lien entre ce module et IIPImage ?

Pardonnez mon éventuelle incompréhension (et d'utiliser Github comme un forum dans ce cas précis), mais je ne comprends pas la référence à IIPImage dans le README. En le lisant pour la première fois, j'avais compris de prime abord que le module IiifServer "embarquait" un serveur IIPImage (ce qui me paraissait assez improbable vu que celui-ci doit être compilé au préalable pour un environnement en particulier, ou s'installer par le biais d'un gestionnaire de paquets type APT...). Or, si je saisis bien, l'API Image de IIIF est entièrement implémentée en PHP dans ce module, sans autre dépendance que les librairies GD ou ImageMagick, donc sans lien avec le logiciel IIPImage en tant que tel. Est-ce effectivement le cas ?

Tiles garbled

When viewing an image via UV/IIIF the initial image is ok, but when you zoom it seems the incorrect sequence of tiles is loaded.

image

You can see an example via https://www.goudatijdmachine.nl/data/document/ark:/60537/b001M1 (image above) or use your own favorite viewer and load https://www.goudatijdmachine.nl/data/iiif/2/35305/manifest (as the effect is also visible in other viewers, I ruled out my viewer).

I'm not sure if this is an issue of IiifServer 3.6.6.6 or ImageServer 3.6.10.3.

Problems with HTML Entity in Manifest

I think I found a bug in version 3.5.16: If the title contains HTML Entities, such as angle brackets, they are displayed correctly in the metadata, but not in the title. The manifest shows that masking does not work for the title, but it does for the metadata. This results in display errors in the viewer. Here is a snippet of the Manifest:

image

Convert command failed when uploading json file

Not sure if this is specifically related to the module, but when I follow the instructions for configuring 3D model support, I get this error when trying to upload the .json file.

Command "/usr/bin/convert '/tmp/omekapfkPng[0]' -auto-orient -background white +repage -alpha remove -thumbnail '800x800>' '/tmp/omekaPriDsY.jpg'" failed with status code 1.

I'm using Omeka S 3.0.1 and IIIF Server 3.6.3.1.

I double-checked that that .json was added the extensions and mime types in global settings. Any other things to look at?

Really appreciate the help and support with your modules!

manifest cannot be built while using S3 media storage

It appears that the ImageSize helper is not able to deal with media stored on an S3 bucket using the Any Cloud version 1.1.4 module. Is S3 currently supported? Stack trace below.

2020-03-02T16:18:51+00:00 ERR (3): Zend\View\Exception\RuntimeException: Failed to get image resolution: square/2297c23419bbb1c7b8b37d6a6877f221afbc689
a.jpg in /var/www/omeka-s/modules/IiifServer/src/View/Helper/ImageSize.php:42
Stack trace:
#0 [internal function]: IiifServer\View\Helper\ImageSize->__invoke(Object(Omeka\Api\Representation\MediaRepresentation), 'square')
#1 /var/www/omeka-s/vendor/zendframework/zend-view/src/Renderer/PhpRenderer.php(397): call_user_func_array(Object(IiifServer\View\Helper\ImageSize), Ar
ray)
#2 /var/www/omeka-s/modules/IiifServer/src/View/Helper/IiifManifest.php(606): Zend\View\Renderer\PhpRenderer->__call('imageSize', Array)
#3 /var/www/omeka-s/modules/IiifServer/src/View/Helper/IiifManifest.php(752): IiifServer\View\Helper\IiifManifest->_iiifThumbnail(Object(Omeka\Api\Repr
esentation\MediaRepresentation))
#4 /var/www/omeka-s/modules/IiifServer/src/View/Helper/IiifManifest.php(287): IiifServer\View\Helper\IiifManifest->_iiifCanvasImage(Object(Omeka\Api\Re
presentation\MediaRepresentation), 1)
#5 /var/www/omeka-s/modules/IiifServer/src/View/Helper/IiifManifest.php(72): IiifServer\View\Helper\IiifManifest->buildManifestItem(Object(Omeka\Api\Re
presentation\ItemRepresentation))
#6 /var/www/omeka-s/modules/IiifServer/src/Controller/PresentationController.php(156): IiifServer\View\Helper\IiifManifest->__invoke(Object(Omeka\Api\R
epresentation\ItemRepresentation))
#7 /var/www/omeka-s/vendor/zendframework/zend-mvc/src/Controller/AbstractActionController.php(78): IiifServer\Controller\PresentationController->itemAction()
#8 /var/www/omeka-s/vendor/zendframework/zend-eventmanager/src/EventManager.php(322): Zend\Mvc\Controller\AbstractActionController->onDispatch(Object(Z
end\Mvc\MvcEvent))
#9 /var/www/omeka-s/vendor/zendframework/zend-eventmanager/src/EventManager.php(179): Zend\EventManager\EventManager->triggerListeners(Object(Zend\Mvc\
MvcEvent), Object(Closure))
#10 /var/www/omeka-s/vendor/zendframework/zend-mvc/src/Controller/AbstractController.php(106): Zend\EventManager\EventManager->triggerEventUntil(Object
(Closure), Object(Zend\Mvc\MvcEvent))
#11 /var/www/omeka-s/vendor/zendframework/zend-mvc/src/DispatchListener.php(138): Zend\Mvc\Controller\AbstractController->dispatch(Object(Zend\Http\Php
Environment\Request), Object(Zend\Http\PhpEnvironment\Response))
#12 /var/www/omeka-s/vendor/zendframework/zend-eventmanager/src/EventManager.php(322): Zend\Mvc\DispatchListener->onDispatch(Object(Zend\Mvc\MvcEvent))
#13 /var/www/omeka-s/vendor/zendframework/zend-eventmanager/src/EventManager.php(179): Zend\EventManager\EventManager->triggerListeners(Object(Zend\Mvc
\MvcEvent), Object(Closure))
#14 /var/www/omeka-s/vendor/zendframework/zend-mvc/src/Application.php(332): Zend\EventManager\EventManager->triggerEventUntil(Object(Closure), Object(
Zend\Mvc\MvcEvent))
#15 /var/www/omeka-s/index.php(21): Zend\Mvc\Application->run()
#16 {main}

Use `related` to link to Omeka Item page from manifest

Currently there is no obvious way to get back to the Omeka site originating the IIIF manifest once that manifest has been reused elsewhere (e.g. an import into Mirador). I'd like to add that link to the related block, but would like to discuss a problem with this strategy before I open a pull request.

The challenge is that generating a URL back to the item page on a site requires access to a site slug. Since items may be shared across multiple Omeka-S sites, and since the IIIF server acts as a shared resource, it does not have access to a site slug.

How can we generate an appropriate URL for a related link from buildManifestItem?

Released version 3.6.13

Hi at all,

i have this error:

[Mon May 15 08:59:46.162390 2023] [proxy_fcgi:error] [pid 535] [client 151.97.200.151:52537] AH01071: Got error 'PHP message: PHP Deprecated: Creation of dynamic property IiifServer\View\Helper\IiifCol
lectionList2::$setting is deprecated in /srv/http/omeka-s-4.0.1/modules/IiifServer/src/View/Helper/IiifCollectionList2.php on line 91', referer: https://cat.unict.it/omeka-s/s/orto-botanico-ed-herbarium/it
em-set?sort_by=title&sort_order=asc&has_markers=&mapping_address=&mapping_radius=&mapping_radius_unit=km

Cannot create JSON with items with resources as property values

Visit a link like http://localhost/omeka-s/iiif/42 wher 42 is the ID of an item which has some properties set to resources as values.

View Helper IiifManifest::buildManifestItem() try to get string representation of values (l.124). However for resource value, it calls AbstractResourceRepresentation::url() which return NULL because query don’t come from admin nor from site.

It makes ValueRepresentation::__toString() return a non string value (NULL) and throw E_RECOVERABLE_ERROR.

Content Search API 1.0 ?

Does the IIIF-Server supports Content Search API, too? I thought to upload hocr to each omeka item. If there is no support can you recommend an easy server solution? Or is it planed to integrate Search API soon?

Accessing big images through IIIF manifests is extremely slow

With IIIF Server and Image Server (Omeka S 4.0.1, iiif server 3.6.12 and image server 3.6.13), opening images through manifests in an external Mirador Viewer page is extremely slow, especially with bigger images. Same images opened in the Opeaseadragon default viewer opens very quickly and the zoom is extremely fluid.
I tried to investigate more and it looks to me the responsible for the slowdown is the IIIF Server, even I cannot be sure as I’m not completely aware of how IIIF Server and Image Server work together.
I try to explain.
I made a test accessing this item: http://corpuspitturafiorentina.bmlonline.it/s/cennino-cennini/item/331 where the image media is opened directly with Openseadragon. Then I open the same media in another browser tab, using Mirador through the button “Confronta immagini in Mirador”.
With the two tab active, I opened the development tool of the browser (F12) and I made a recording of the same zoom in both the interface.
What I saw then is that in Mirador the number of calls are exatly two times those in Openseadragon.
In fact, while the request in Openseadragon default viewer are directly to the tiles of the image, using IIIF Manifest in Mirador request a double call for each tile, where the first is for the IIIF default.jpg resource of the specific tile, and the second is the redirect to the real image.
This is an example of a tile call:

Openseadrogn (not using IIIF)
13:10:52.862 GEThttp://corpuspitturafiorentina.bmlonline.it/files/tile/gentile.adorazione/gentile.adorazione.2018.martellucci_files/12/2_8.jpg
[HTTP/1.1 200 OK 102ms]

Mirador (using IIIF)
13:10:40.790
GEThttp://corpuspitturafiorentina.bmlonline.it/iiif/2/14377/4096,16384,2048,2048/256,/0/default.jpg
[HTTP/1.1 302 Found 961ms]

13:10:41.743
GEThttp://corpuspitturafiorentina.bmlonline.it/files/tile/gentile.adorazione/gentile.adorazione.2018.martellucci_files/12/2_8.jpg
[HTTP/1.1 200 OK 65ms]

As one can see, when IIIF Manifest is involved, the call for the default.jpg took about ten times that for the real image, and this seems to be the reason of the slowdown and timeouts I see.

Is this behavior expected? Is there any trick to make that process faster?
Checking other IIIF servers, those don’t show the same behavior when calling for resources like /iiif/2/14377/4096,16384,2048,2048/256,/0/default.jpg, i.e. I don’t see the same systematic redirection I see in Omeka.

Another strange things I noticed, is that Mirador, using the IIIF Manifest provided by IIIF Server in OMEKA S, seem to load nonexistent tiles at the border of the image that are not called when same image is opened in the default Openseadragon viewer

Import tiff files before tiling

I imported tiff files and I used IIIFServer to tile them (with the Bulk tiler integrated inside the module configuration settings). I tested both Zoomify and Deep zoom image methods ; its seems to work according to the job log. But mirador does not display any file at the end.

Is it possible (recommended ?) to import a file directly in tiff and tile it after inside Omeka? If not what is the best way to keep quality at the top?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.