#!/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('