"""
Zoomify Structure Module
------------------------
Classes necessary for Zoomify files processing

(C) Copyright 2006 
Klokan Petr Pridal (www.klokan.cz)
"""

__revision__ = "2006-11-27"

from math import ceil
from pprint import pformat

class ZoomifyLevel( object ):
    """One level of zoomify pyramid"""

    def __init__(self, width, height, tilesize=256 ):
        self.width = width
        self.height = height
        self.xtiles = int( ceil( width / float(tilesize) ) )
        self.ytiles = int( ceil( height / float(tilesize) ) )

    def __len__(self):
        return self.xtiles * self.ytiles

    def __repr__(self):
        return "Image: %s x %s pixels; %s tiles in %s x %s" % (
            self.width, self.height, len(self), self.xtiles, self.ytiles )

class ZoomifyPyramid( object ):
    """Zoomify pyramid"""

    def __init__(self, width, height, tilesize=256 ):
        self.width = width
        self.height = height
        self.tilesize = tilesize
        self._pyramid = []
        level = ZoomifyLevel( width, height, tilesize )
        while level.width > tilesize or level.height > tilesize:
            self._pyramid.append(level)
            level = ZoomifyLevel( level.width / 2, level.height / 2, tilesize )
            # floor() not needed. Integer arithmetic
        self._pyramid.append(level)
        self._pyramid.reverse()

    def __len__(self):
        return len( self._pyramid )

    def __repr__(self):
        return pformat(self._pyramid)

    def tiles_upto_level(self, level):
        """Number of tiles up to given level of pyramid"""
        return sum( map( len, self._pyramid[:level] ) )

    def levels(self):
        """Number of levels in pyramid. Available also as len(pyramid)"""
        return len( self )

    def tiles(self):
        """Total count of tiles in pyramid"""
        return self.tiles_upto_level( len( self._pyramid ) )

    def tile_index(self, level, x_coordinate, y_coordinate):
        """Index of tile at given coordinates"""
        return ( x_coordinate +
            (y_coordinate-1) * self._pyramid[level].xtiles +
            self.tiles_upto_level( level-1 ) )

    def tile_filename(self, level, x_coordinate, y_coordinate):
        """Filename of tile at given coordinates"""
        return "TileGroup%s/%s-%s-%s.jpg" % (
            self.tile_index( level, x_coordinate, y_coordinate) / 256,
            level, x_coordinate, y_coordinate )

if __name__ == '__main__':
    PYRAMID = ZoomifyPyramid(5000, 1000, 256)

    print PYRAMID
    print "Number of levels: %s" % PYRAMID.levels()
    print "Number of tiles: %s" % PYRAMID.tiles()
    print "Index/filename for tile at (l, x, y)=(4, 5, 7): %s %s" % (
    PYRAMID.tile_index(4, 5, 7), PYRAMID.tile_filename(4, 5, 7) )