X-Git-Url: https://scm.cri.minesparis.psl.eu/git/Photo.git/blobdiff_plain/b0a7e10b4f32cf74864bb53268ca4d3080f23bc0..6c41809185e322ce2d30e98234f71144f78f06c0:/TileSupport.py?ds=sidebyside diff --git a/TileSupport.py b/TileSupport.py deleted file mode 100644 index 5b777cc..0000000 --- a/TileSupport.py +++ /dev/null @@ -1,190 +0,0 @@ -# -*- coding: utf-8 -*- -####################################################################################### -# Photo is a part of Plinn - http://plinn.org # -# Copyright (C) 2004-2007 Benoît PIN # -# # -# This program is free software; you can redistribute it and/or # -# modify it under the terms of the GNU General Public License # -# as published by the Free Software Foundation; either version 2 # -# of the License, or (at your option) any later version. # -# # -# This program is distributed in the hope that it will be useful, # -# but WITHOUT ANY WARRANTY; without even the implied warranty of # -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # -# GNU General Public License for more details. # -# # -# You should have received a copy of the GNU General Public License # -# along with this program; if not, write to the Free Software # -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -####################################################################################### -""" Tile support module - - - -""" - -from AccessControl import ClassSecurityInfo -from AccessControl import Unauthorized -from AccessControl import getSecurityManager -from AccessControl.Permissions import view, change_images_and_files -from PIL import Image as PILImage -from math import ceil -from blobbases import Image -from xmputils import TIFF_ORIENTATIONS -from cache import memoizedmethod -from BTrees.OOBTree import OOBTree -from BTrees.IOBTree import IOBTree -from ppm import PPMFile -from threading import Lock -from subprocess import Popen, PIPE -from tempfile import TemporaryFile - -JPEG_ROTATE = 'jpegtran -rotate %d' -JPEG_FLIP = 'jpegtran -flip horizontal' - -def runOnce(lock): - """ Decorator. exit if already running """ - - def wrapper(f): - def method(*args, **kw): - if not lock.locked() : - lock.acquire() - try: - return f(*args, **kw) - finally: - lock.release() - else : - return False - return method - return wrapper - - - -class TileSupport : - """ Mixin class to generate tiles from image """ - - security = ClassSecurityInfo() - tileSize = 256 - tileGenerationLock = Lock() - - def __init__(self) : - self._tiles = OOBTree() - - security.declarePrivate('makeTilesAt') - @runOnce(tileGenerationLock) - def makeTilesAt(self, zoom): - """generates tiles at zoom level""" - - if self._tiles.has_key(zoom) : - return True - - assert zoom <= 1, "zoom arg must be <= 1 found: %s" % zoom - - ppm = self._getPPM() - if zoom < 1 : - ppm = ppm.resize(ratio=zoom) - - self._makeTilesAt(zoom, ppm) - return True - - def _getPPM(self) : - bf = self._getJpegBlob() - f = bf.open('r') - - orientation = self.tiffOrientation() - rotation, flip = TIFF_ORIENTATIONS.get(orientation, (0, False)) - - if rotation and flip : - tf = TemporaryFile(mode='w+') - pRot = Popen(JPEG_ROTATE % rotation - , stdin=f - , stdout=PIPE - , shell=True) - pFlip = Popen(JPEG_FLIP - , stdin=pRot.stdout - , stdout=tf - , shell=True) - pFlip.wait() - f.close() - tf.seek(0) - f = tf - - elif rotation : - tf = TemporaryFile(mode='w+') - pRot = Popen(JPEG_ROTATE % rotation - , stdin=f - , stdout=tf - , shell=True) - pRot.wait() - f.close() - tf.seek(0) - f = tf - - elif flip : - tf = TemporaryFile(mode='w+') - pFlip = Popen(JPEG_FLIP - , stdin=f - , stdout=tf - , shell=True) - pFlip.wait() - f.close() - tf.seek(0) - f = tf - - ppm = PPMFile(f, tileSize=self.tileSize) - f.close() - return ppm - - def _makeTilesAt(self, zoom, ppm): - hooks = self._getAfterTilingHooks() - self._tiles[zoom] = IOBTree() - bgColor = getattr(self, 'tiles_background_color', '#fff') - - for x in xrange(ppm.tilesX) : - self._tiles[zoom][x] = IOBTree() - for y in xrange(ppm.tilesY) : - tile = ppm.getTile(x, y) - for hook in hooks : - hook(self, tile) - - # fill with solid color - if min(tile.size) < self.tileSize : - blankTile = PILImage.new('RGB', (self.tileSize, self.tileSize), bgColor) - box = (0,0) + tile.size - blankTile.paste(tile, box) - tile = blankTile - - zImg = Image('tile', 'tile', '', content_type='image/jpeg') - out = zImg.open('w') - tile.save(out, 'JPEG', quality=90) - zImg.updateFormat(out.tell(), tile.size, 'image/jpeg') - out.close() - - self._tiles[zoom][x][y] = zImg - - def _getAfterTilingHooks(self) : - return [] - - - security.declareProtected(view, 'getAvailableZooms') - def getAvailableZooms(self): - zooms = list(self._tiles.keys()) - zooms.sort() - return zooms - - security.declareProtected(view, 'getTile') - def getTile(self, REQUEST, RESPONSE, zoom=1, x=0, y=0): - """ publishes tile - """ - zoom, x, y = float(zoom), int(x), int(y) - if not self._tiles.has_key(zoom) : - sm = getSecurityManager() - if not sm.checkPermission(change_images_and_files, self) : - raise Unauthorized("Tiling arbitrary zoom unauthorized") - if self.makeTilesAt(zoom) : - tile = self._tiles[zoom][x][y] - return tile.index_html(REQUEST=REQUEST, RESPONSE=RESPONSE) - else : - tile = self._tiles[zoom][x][y] - return tile.index_html(REQUEST=REQUEST, RESPONSE=RESPONSE) -