#!/usr/bin/python
#
# OpenSlide, a library for reading whole slide image files
#
# Copyright (c) 2007-2012 Carnegie Mellon University
# Copyright (c) 2011 Google, Inc.
# All rights reserved.
#
# OpenSlide is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, version 2.1.
#
# OpenSlide 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with OpenSlide. If not, see
# .
#
from __future__ import division
from ConfigParser import RawConfigParser, NoOptionError, Error as ConfigError
import io
import os
from StringIO import StringIO
import struct
import sys
import zlib
class Reporter(object):
def __init__(self, level=0):
self._level = level
self._indent = ' ' * level * 2
def __call__(self, key, value):
print '%s%-30s %s' % (self._indent, key + ':', value)
def child(self, desc):
print '%s%s:' % (self._indent, desc)
return type(self)(self._level + 1)
class SlidedatHierarchy(object):
SECTION = 'HIERARCHICAL'
def __init__(self, dat):
self._by_id = []
self._by_name = {}
self._next_offset = 0
layers = dat.getint(self.SECTION, self.LAYER_COUNT_KEY)
for layer_id in range(layers):
layer = HierLayer(self, dat, layer_id)
self._by_id.append(layer)
self._by_name[layer.name] = layer
def __iter__(self):
return iter(self._by_id)
def get_layer_by_name(self, name):
return self._by_name[name]
def next_offset(self):
self._next_offset += 1
return self._next_offset - 1
class HierTree(SlidedatHierarchy):
LAYER_COUNT_KEY = 'HIER_COUNT'
LAYER_NAME_KEY = 'HIER_%d_NAME'
LAYER_SECTION_KEY = 'HIER_%d_SECTION'
LEVEL_COUNT_KEY = 'HIER_%d_COUNT'
LEVEL_NAME_KEY = 'HIER_%d_VAL_%d'
LEVEL_SECTION_KEY = 'HIER_%d_VAL_%d_SECTION'
class NonHierTree(SlidedatHierarchy):
LAYER_COUNT_KEY = 'NONHIER_COUNT'
LAYER_NAME_KEY = 'NONHIER_%d_NAME'
LAYER_SECTION_KEY = 'NONHIER_%d_SECTION'
LEVEL_COUNT_KEY = 'NONHIER_%d_COUNT'
LEVEL_NAME_KEY = 'NONHIER_%d_VAL_%d'
LEVEL_SECTION_KEY = 'NONHIER_%d_VAL_%d_SECTION'
class HierLayer(object):
def __init__(self, h, dat, layer_id):
self.name = dat.get(h.SECTION, h.LAYER_NAME_KEY % layer_id)
self.section = dat.get(h.SECTION, h.LAYER_SECTION_KEY % layer_id)
self.levels = dat.getint(h.SECTION, h.LEVEL_COUNT_KEY % layer_id)
self._by_id = []
self._by_name = {}
for level_id in range(self.levels):
level = HierLevel(h, dat, layer_id, level_id)
self._by_id.append(level)
self._by_name[level.name] = level
def __iter__(self):
return iter(self._by_id)
def get_level_by_name(self, name):
return self._by_name[name]
def get_level_by_id(self, id):
return self._by_id[id]
class HierLevel(object):
def __init__(self, h, dat, layer_id, level_id):
self.name = dat.get(h.SECTION,
h.LEVEL_NAME_KEY % (layer_id, level_id))
self.section = dat.get(h.SECTION,
h.LEVEL_SECTION_KEY % (layer_id, level_id))
self.offset = h.next_offset()
def read_zoom_level(r, dat, section):
r('Concat factor', dat.getint(section, 'IMAGE_CONCAT_FACTOR'))
r('Image format', dat.get(section, 'IMAGE_FORMAT'))
r('Image width', dat.getint(section, 'DIGITIZER_WIDTH'))
r('Image height', dat.getint(section, 'DIGITIZER_HEIGHT'))
r('Overlap X', dat.getfloat(section, 'OVERLAP_X'))
r('Overlap Y', dat.getfloat(section, 'OVERLAP_Y'))
fill = dat.getint(section, 'IMAGE_FILL_COLOR_BGR')
# Swap to RGB
fill = struct.unpack('I', fill))[0] >> 8
r('Background', '%x' % fill)
def read_len(f, size):
ret = f.read(size)
assert(len(ret) == size)
return ret
def read_int32(f):
buf = f.read(4)
assert(len(buf) == 4)
return struct.unpack('