Exemplo n.º 1
0
 def test03_generate(self):
     """Test generation of a static image."""
     # dryrun covers most
     tmp1 = tempfile.mkdtemp()
     os.mkdir(os.path.join(tmp1, 'a'))
     try:
         # no canonical syntax with osd_version='1.0.0'
         s = IIIFStatic(dst=tmp1, tilesize=512,
                        api_version='1.1', osd_version='1.0.0', dryrun=True)
         with MyLogCapture('iiif.static') as lc:
             s.generate(src='testimages/starfish_1500x2000.png',
                        identifier='a')
         self.assertTrue(re.search(' / a/info.json', lc.all_msgs))
         self.assertTrue(
             re.search(' / a/1024,1536,476,464/476,464/0/native.jpg', lc.all_msgs))
         # largest full region (and symlink from w,h)
         self.assertTrue(
             re.search(' / a/full/375,500/0/native.jpg', lc.all_msgs))
         # smallest full region
         self.assertTrue(
             re.search(' / a/full/1,1/0/native.jpg', lc.all_msgs))
         # v2.0
         s = IIIFStatic(dst=tmp1, tilesize=512,
                        api_version='2.0', dryrun=True)
         with MyLogCapture('iiif.static') as lc:
             s.generate(src='testimages/starfish_1500x2000.png',
                        identifier='a')
         self.assertTrue(re.search(' / a/info.json', lc.all_msgs))
         self.assertTrue(
             re.search(' / a/1024,1536,476,464/476,/0/default.jpg', lc.all_msgs))
         # largest full region (and symlink from w,h)
         self.assertTrue(
             re.search(' / a/full/375,/0/default.jpg', lc.all_msgs))
         self.assertTrue(
             re.search(' / a/full/375,500 -> a/full/375,', lc.all_msgs))
         # smallest full region
         self.assertTrue(
             re.search(' / a/full/1,/0/default.jpg', lc.all_msgs))
         self.assertTrue(
             re.search(' / a/full/1,1 -> a/full/1,', lc.all_msgs))
     finally:
         shutil.rmtree(tmp1)
     # real write
     tmp2 = tempfile.mkdtemp()
     try:
         s = IIIFStatic(dst=tmp2, tilesize=1024, api_version='2.0')
         with MyLogCapture('iiif.static') as lc:
             s.generate(src='testimages/starfish_1500x2000.png',
                        identifier='b')
         self.assertTrue(os.path.isfile(os.path.join(tmp2, 'b/info.json')))
         self.assertTrue(os.path.isfile(os.path.join(
             tmp2, 'b/1024,1024,476,976/476,/0/default.jpg')))
         self.assertTrue(os.path.isfile(
             os.path.join(tmp2, 'b/full/1,/0/default.jpg')))
     finally:
         shutil.rmtree(tmp2)
Exemplo n.º 2
0
 def test01_init(self):
     """Test initialization."""
     s = IIIFStatic()
     self.assertEqual(s.api_version, '2.0')  # default is 2.0
     self.assertEqual(s.tilesize, 512)
     s = IIIFStatic(src='abc', dst='def', tilesize=1024,
                    api_version='2', dryrun=True)
     self.assertEqual(s.src, 'abc')
     self.assertEqual(s.dst, 'def')
     self.assertEqual(s.tilesize, 1024)
     self.assertEqual(s.api_version, '2.0')
     self.assertEqual(s.dryrun, True)
     s = IIIFStatic(src='abc', dst='def', tilesize=1024,
                    api_version='1', dryrun=True)
     self.assertEqual(s.api_version, '1.1')
Exemplo n.º 3
0
def main():

    if (sys.version_info < (2, 6)):
        sys.exit("This program requires python version 2.6 or later")

    # Options and arguments
    p = optparse.OptionParser(
        description='IIIF Image API static file generator',
        usage='usage: %prog [options] file|path (-h for help)',
        version='%prog ' + __version__)

    p.add_option('--dst',
                 '-d',
                 action='store',
                 default='/tmp',
                 help="destination directory [/tmp default]")
    p.add_option('--tilesize',
                 '-t',
                 action='store',
                 type='int',
                 default=512,
                 help="tilesize in pixels [512 default]")
    p.add_option('--api-version',
                 '--api',
                 '-a',
                 action='store',
                 default='1.1',
                 help="API version, may be 1.1 [default] or 2.0")
    p.add_option('--dryrun',
                 '-n',
                 action='store_true',
                 help="do not write anything, say what would be done")
    p.add_option('--verbose', '-v', action='store_true', help="verbose")

    (args, sources) = p.parse_args()

    logging.basicConfig(format='%(name)s: %(message)s',
                        level=(logging.INFO if
                               (args.verbose) else logging.WARNING))
    logger = logging.getLogger(os.path.basename(__file__))

    if (len(sources) == 0):
        logger.warn("no sources specified, nothing to do, bye! (-h for help)")
    else:
        for source in sources:
            # File or directory (or neither)?
            sg = IIIFStatic(dst=args.dst,
                            tilesize=args.tilesize,
                            api_version=args.api_version,
                            dryrun=args.dryrun)
            if (os.path.isfile(source)):
                logger.info("source file: %s" % (source))
                sg.generate(source)
            elif (os.path.isdir(source)):
                raise Exception("source dir: %s - FIXME: not yet supported" %
                                (source))
            else:
                logger.warn("ignoring source '%s': neither file nor path" %
                            (source))
Exemplo n.º 4
0
 def test02_parse_extra(self):
     """Test parse_extra."""
     s = IIIFStatic()
     r = s.parse_extra('/0,0,100,100/10,10/0/default.jpg')
     self.assertEqual(r.region_xywh, [0, 0, 100, 100])
     r = s.parse_extra('full/full/0/default.jpg')
     self.assertEqual(r.region_full, True)
     # Error cases
     self.assertRaises(IIIFRequestError, s.parse_extra, '')
     self.assertRaises(IIIFRequestError, s.parse_extra, '/bad/')
     self.assertRaises(IIIFStaticError, s.parse_extra, 'info.json')
Exemplo n.º 5
0
 def test01_init(self):
     """Test initialization."""
     s = IIIFStatic()
     self.assertEqual(s.api_version, '2.0')  # default is 2.0
     self.assertEqual(s.tilesize, 512)
     s = IIIFStatic(src='abc', dst='def', tilesize=1024,
                    api_version='2', dryrun=True)
     self.assertEqual(s.src, 'abc')
     self.assertEqual(s.dst, 'def')
     self.assertEqual(s.tilesize, 1024)
     self.assertEqual(s.api_version, '2.0')
     self.assertEqual(s.dryrun, True)
     s = IIIFStatic(src='abc', dst='def', tilesize=1024,
                    api_version='1', dryrun=True)
     self.assertEqual(s.api_version, '1.1')
     # Test passing generator flag
     s = IIIFStatic(generator=True)
     self.assertEqual(s.manipulator_klass, IIIFManipulatorGen)
     # Test extra
     s = IIIFStatic(extras=['/full/full/0/default.png'])
     self.assertEqual(len(s.extras), 1)
Exemplo n.º 6
0
 def test04_generate_tile(self):
     """Test generation of a tile."""
     # most tested via other calls, make sure zero size skip works
     tmp1 = tempfile.mkdtemp()
     os.mkdir(os.path.join(tmp1, 'a'))
     try:
         s = IIIFStatic(dst=tmp1, tilesize=512, api_version='2.0')
         s.identifier = 'fgh'
         s.src = 'testimages/starfish_1500x2000.png'
         with MyLogCapture('iiif.static') as lc:
             s.generate_tile(region='full', size=[0, 1])
         self.assertTrue(re.search(r'zero size, skipped', lc.all_msgs))
     finally:
         shutil.rmtree(tmp1)
Exemplo n.º 7
0
 def generate_deep_zoom(self, jekyll_site_dir):
     self.log_status('Downloading deep zoom images')
     imagedir = os.path.join(jekyll_site_dir, self.image_dir)
     # If exporting to GitHub, add the repo name to the path.
     _prefix = os.path.join(
         os.sep, self.github_repo,
         self.image_dir) if self.github_repo else os.path.join(
             os.sep, self.image_dir)
     staticgen = IIIFStatic(dst=imagedir, prefix=_prefix)
     for teipage in self.tei.page_list:
         for graphic in teipage.graphics:
             if graphic.rend == 'full':
                 imgsrc = os.path.join(jekyll_site_dir, graphic.url)
                 iiif_img = IIIFImageClient.init_from_url(graphic.url)
                 staticgen.generate(imgsrc, identifier=iiif_img.image_id)
Exemplo n.º 8
0
 def test02_generate(self):
     tmp = tempfile.mkdtemp()
     try:
         s = IIIFStatic(src='testimages/starfish_1500x2000.png',
                        dst=tmp,
                        tilesize=1024,
                        api_version='1',
                        dryrun=True)
         with capture_stdout() as capturer:
             s.generate(identifier='a')
         self.assertTrue(
             re.search(' / a/1024,1024,476,976/476,976/0/native.jpg',
                       capturer.result))
         self.assertTrue(
             re.search(' / a/full/1,1/0/native.jpg', capturer.result))
     finally:
         shutil.rmtree(tmp)
Exemplo n.º 9
0
 def test08_setup_destination(self):
     """Test setip_destination."""
     s = IIIFStatic()
     # no dst
     self.assertRaises(Exception, s.setup_destination)
     # now really create dir
     tmp = tempfile.mkdtemp()
     try:
         # no dst
         s.identifier = 'a'
         s.dst = None
         self.assertRaises(IIIFStaticError, s.setup_destination)
         # dst and no identifier
         s.src = 'a/b.ext'
         s.dst = os.path.join(tmp, 'xyz')
         s.identifier = None
         s.setup_destination()
         self.assertTrue(os.path.isdir(tmp))
         self.assertTrue(os.path.isdir(s.dst))
         self.assertTrue(os.path.isdir(os.path.join(s.dst, 'b')))
         self.assertEqual(s.identifier, 'b')
         # dst and identifier
         s.src = 'a/b.ext'
         s.dst = os.path.join(tmp, 'zyx')
         s.identifier = 'c'
         s.setup_destination()
         self.assertTrue(os.path.isdir(s.dst))
         self.assertTrue(os.path.isdir(os.path.join(s.dst, 'c')))
         self.assertEqual(s.identifier, 'c')
         # dst path is file
         s.dst = os.path.join(tmp, 'exists1')
         open(s.dst, 'w').close()
         self.assertRaises(Exception, s.setup_destination)
         # dst and identifier, path is file
         s.identifier = 'exists2'
         s.dst = tmp
         open(os.path.join(s.dst, s.identifier), 'w').close()
         self.assertRaises(Exception, s.setup_destination)
         # dst and identifier, both dirs exist and OK
         s.dst = tmp
         s.identifier = 'id1'
         os.mkdir(os.path.join(s.dst, s.identifier))
         s.setup_destination()  # nothing created, no exception
     finally:
         shutil.rmtree(tmp)
Exemplo n.º 10
0
    def __init__(self, generate_image_pyramid: bool = True):
        """Inits ImageProcessor and configures manifest factory.

        :param generate_image_pyramid:if True, pyramid map will be generated. Else, only manifest is generated.
        """
        if not os.path.exists(MANIFEST_OUTPUT_DIR):
            os.makedirs(MANIFEST_OUTPUT_DIR)
        self._manifest_factory = ManifestFactory()
        self._manifest_factory.set_base_prezi_uri(MANIFEST_BASE_URL)
        self._manifest_factory.set_base_prezi_dir(MANIFEST_OUTPUT_DIR)
        self._manifest_factory.set_base_image_uri(IMAGE_BASE_URL)
        self._manifest_factory.set_iiif_image_info(2.0, 1)  # Version, ComplianceLevel

        self._image_reader = ImageReader(IMAGE_SOURCE_DIR)

        if generate_image_pyramid:
            self._tile_generator = IIIFStatic(dst=IMAGE_FILE_OUTPUT_DIR, prefix=IMAGE_BASE_URL)

        self._generate_images = generate_image_pyramid
Exemplo n.º 11
0
 def test04_setup_destination(self):
     s = IIIFStatic()
     # no dst
     self.assertRaises(Exception, s.setup_destination)
     # now really create dir
     tmp = tempfile.mkdtemp()
     try:
         # dst and no identifier
         s.dst = os.path.join(tmp, 'xyz')
         s.identifier = None
         s.setup_destination()
         self.assertTrue(os.path.isdir(s.dst))
         self.assertEqual(s.outd, tmp)
         self.assertEqual(s.identifier, 'xyz')
         # dst and identifier
         s.dst = os.path.join(tmp, 'zyx')
         s.identifier = 'abc'
         s.setup_destination()
         self.assertTrue(os.path.isdir(s.dst))
         self.assertTrue(os.path.isdir(os.path.join(s.dst, 'abc')))
         self.assertEqual(s.outd, s.dst)
         self.assertEqual(s.identifier, 'abc')
         # dst path is file
         s.dst = os.path.join(tmp, 'exists1')
         open(s.dst, 'w').close()
         self.assertRaises(Exception, s.setup_destination)
         # dst and identifier, path is file
         s.identifier = 'exists2'
         s.dst = tmp
         open(os.path.join(s.dst, s.identifier), 'w').close()
         self.assertRaises(Exception, s.setup_destination)
         # dst and identifier, both dirs exist and OK
         s.outd = None
         s.dst = tmp
         s.identifier = 'id1'
         os.mkdir(os.path.join(s.dst, s.identifier))
         s.setup_destination()
         self.assertEqual(s.outd, tmp)
     finally:
         shutil.rmtree(tmp)
Exemplo n.º 12
0
def main():
    """Parse arguments, instantiate IIIFStatic, run."""
    if (sys.version_info < (2, 6)):
        sys.exit("This program requires python version 2.6 or later")

    # Options and arguments
    p = optparse.OptionParser(
        description='IIIF Image API static file generator',
        usage='usage: %prog [options] file [[file2..]] (-h for help)',
        version='%prog ' + __version__)

    p.add_option('--dst',
                 '-d',
                 action='store',
                 default='/tmp',
                 help="Destination directory for images [default '%default']")
    p.add_option('--tilesize',
                 '-t',
                 action='store',
                 type='int',
                 default=512,
                 help="Tilesize in pixels [default %default]")
    p.add_option('--api-version',
                 '--api',
                 '-a',
                 action='store',
                 default='2.1',
                 help="API version, may be 1.1, 2.0 or 2.1 [default %default]")
    p.add_option(
        '--prefix',
        '-p',
        action='store',
        default=None,
        help=
        "URI prefix for where the images will be served from (default '%default'). "
        "An empty prefix may be OK if the HTML page including the image shares the "
        "the same root on the same server as the images, otherwise a full URL should "
        "be specified. This is used to construct the @id in the info.json")
    p.add_option(
        '--identifier',
        '-i',
        action='store',
        default=None,
        help=
        "Identifier for the image that will be used in place of the filename "
        "(minus extension). Notes that this option cannot be used if more than "
        "one image file is to be processed")
    p.add_option(
        '--write-html',
        action='store',
        default=None,
        help=
        "Write HTML page to the specified directory using the 'identifier.html' "
        "as the filename. HTML will launch OpenSeadragon for this image and to "
        "display some of information about info.json and tile locations. HTML will "
        "assume OpenSeadragon at relative path openseadragonVVV/openseadragon.min.js "
        "and user-interface icons in openseadragonVVV/images, where VVV are the "
        "three parts of the version number. The --include-osd flag is also specified "
        "then OpenSeadragon will be copied to these locations")
    p.add_option('--include-osd',
                 action='store_true',
                 help="Include OpenSeadragon files with --write-html flag")
    p.add_option(
        '--osd-version',
        action='store',
        default='2.0.0',
        help=
        "Generate static images for older versions of OpenSeadragon. Use of versions "
        "prior to 1.2.1 will force use of /w,h/ for size parameter instead of /w,/. "
        "Likely useful only in combination with --api-version=1.1 "
        "[default %default]")
    p.add_option(
        '--osd-width',
        action='store',
        type='int',
        default='500',
        help="Width of OpenSeadragon pane in pixels. Applies only with "
        "--write-html [default %default]")
    p.add_option(
        '--osd-height',
        action='store',
        type='int',
        default='500',
        help="Height of OpenSeadragon pane in pixels. Applies only with "
        "--write-html [default %default]")
    p.add_option(
        '--generator',
        action='store_true',
        default=False,
        help="Use named generator modules in iiif.generators package instead "
        "of a starting image [default %default]")
    p.add_option(
        '--max-image-pixels',
        action='store',
        type='int',
        default=0,
        help="Set the maximum number of pixels in an image. A non-zero value "
        "will set a hard limit on the image size. If left unset then the "
        "default configuration of the Python Image Libary (PIL) will give "
        "a DecompressionBombWarning if the image size exceeds a default "
        "maximum, but otherwise continue as normal")
    p.add_option('--dryrun',
                 '-n',
                 action='store_true',
                 help="Do not write anything, say what would be done")
    p.add_option('--quiet',
                 '-q',
                 action='store_true',
                 help="Quite (no output unless there is a warning/error)")
    p.add_option('--verbose', '-v', action='store_true', help="Verbose")

    (opt, sources) = p.parse_args()

    level = logging.DEBUG if (opt.verbose) else \
        logging.WARNING if (opt.quiet) else logging.INFO
    logging.basicConfig(format='%(name)s: %(message)s', level=level)
    logger = logging.getLogger(os.path.basename(__file__))

    if (not opt.write_html and opt.include_osd):
        logger.warn(
            "--include-osd has no effect without --write-html, ignoring")
    if (len(sources) == 0):
        logger.warn("No sources specified, nothing to do, bye! (-h for help)")
    elif (len(sources) > 1 and opt.identifier):
        logger.error(
            "Cannot use --identifier/-i option with multiple sources, aborting."
        )
    else:
        try:
            sg = IIIFStatic(dst=opt.dst,
                            tilesize=opt.tilesize,
                            api_version=opt.api_version,
                            dryrun=opt.dryrun,
                            prefix=opt.prefix,
                            osd_version=opt.osd_version,
                            generator=opt.generator,
                            max_image_pixels=opt.max_image_pixels)
            for source in sources:
                # File or directory (or neither)?
                if (os.path.isfile(source) or opt.generator):
                    logger.info("source file: %s" % (source))
                    sg.generate(source, identifier=opt.identifier)
                    if (opt.write_html):
                        sg.write_html(html_dir=opt.write_html,
                                      include_osd=opt.include_osd,
                                      osd_width=opt.osd_width,
                                      osd_height=opt.osd_height)
                elif (os.path.isdir(source)):
                    logger.warn(
                        "Ignoring source '%s': directory coversion not supported"
                        % (source))
                else:
                    logger.warn("Ignoring source '%s': neither file nor path" %
                                (source))
        except (IIIFStaticError, IIIFError) as e:
            # catch known errors and report nicely...
            logger.error("Error: " + str(e))
Exemplo n.º 13
0
 def test02_get_osd_config(self):
     """Test get_osd_config."""
     s = IIIFStatic()
     self.assertEqual(s.get_osd_config('2.0.0')['use_canonical'], True)
     self.assertRaises(IIIFStaticError, s.get_osd_config, 'abc')
     self.assertRaises(IIIFStaticError, s.get_osd_config, '0.0.0')
Exemplo n.º 14
0
 def test08_write_html(self):
     """Test write_html."""
     s = IIIFStatic()
     # bad output dir
     self.assertRaises(Exception, s.write_html,
                       '/tmp/path_does_no_exist_(i_hope)')
     # write to good path
     tmp = tempfile.mkdtemp()
     s.identifier = 'abc1'
     s.write_html(tmp)
     self.assertTrue(os.path.isfile(os.path.join(tmp, 'abc1.html')))
     # write to subdir of good path
     tmp = tempfile.mkdtemp()
     s.identifier = 'abc2'
     tmp2 = os.path.join(tmp, 'xyz')
     s.write_html(tmp2)
     self.assertTrue(os.path.isfile(os.path.join(tmp2, 'abc2.html')))
     # write to good path with osd
     tmp = tempfile.mkdtemp()
     s.identifier = 'abc3'
     s.write_html(tmp, include_osd=True)
     self.assertTrue(os.path.isfile(os.path.join(tmp, 'abc3.html')))
     self.assertTrue(os.path.isfile(os.path.join(
         tmp, 'openseadragon200/openseadragon.min.js')))
     self.assertTrue(s.copied_osd)
     # add another, with osd already present (and marked as such)
     s.identifier = 'abc4'
     with LogCapture('iiif.static') as lc:
         s.write_html(tmp, include_osd=True)
     self.assertTrue(os.path.isfile(os.path.join(tmp, 'abc4.html')))
     self.assertTrue(os.path.isfile(os.path.join(
         tmp, 'openseadragon200/openseadragon.min.js')))
     self.assertTrue(s.copied_osd)
     self.assertEqual(lc.records[-1].msg, 'OpenSeadragon already copied')
     # add yet another, with osd already present (but not marked)
     s.identifier = 'abc5'
     s.copied_osd = False
     with LogCapture('iiif.static') as lc:
         s.write_html(tmp, include_osd=True)
     self.assertTrue(os.path.isfile(os.path.join(tmp, 'abc5.html')))
     self.assertTrue(os.path.isfile(os.path.join(
         tmp, 'openseadragon200/openseadragon.min.js')))
     self.assertTrue(s.copied_osd)
     self.assertTrue(re.search(r'OpenSeadragon images directory .* already exists',
                               lc.records[-1].msg))
     # add another but with a prefix
     s.identifier = 'abc6'
     s.prefix = 'z/y/x'
     s.copied_osd = False
     s.write_html(tmp, include_osd=True)
     html_file = os.path.join(tmp, 'abc6.html')
     self.assertTrue(os.path.isfile(html_file))
     with open(html_file, 'r') as x:
         html = x.read()
     self.assertTrue(re.search(r'z/y/x/abc6/info.json', html))
     # bad write to existing path
     tmp = tempfile.mkdtemp()
     tmp2 = os.path.join(tmp, 'file')
     open(tmp2, 'w').close()
     s.identifier = 'abc4'
     self.assertRaises(Exception, s.write_html, tmp2)