def setup(self): self.cache_dir = tempfile.mkdtemp() self.file_cache = FileCache(cache_dir=self.cache_dir, file_ext='png') self.grid = TileGrid(SRS(4326), bbox=[-180, -90, 180, 90]) self.client = MockTileClient() self.source = TiledSource(self.grid, self.client) self.image_opts = ImageOptions(format='image/png') self.tile_mgr = TileManager(self.grid, self.file_cache, [self.source], 'png', image_opts=self.image_opts)
def setup(self): self.file_cache = MockFileCache('/dev/null', 'png', lock_dir=tmp_lock_dir) self.grid = TileGrid(SRS(4326), bbox=[-180, -90, 180, 90]) self.client = MockWMSClient() self.source = WMSSource(self.client) self.image_opts = ImageOptions(resampling='nearest') self.tile_mgr = TileManager(self.grid, self.file_cache, [self.source], 'png', meta_size=[2, 2], meta_buffer=0, image_opts=self.image_opts) self.layer = CacheMapLayer(self.tile_mgr, image_opts=default_image_opts)
def setup(self): self.file_cache = MockFileCache('/dev/null', 'png', lock_dir=tmp_lock_dir) self.grid = TileGrid(SRS(4326), bbox=[-180, -90, 180, 90]) self.source_grid = TileGrid(SRS(4326), bbox=[0, -90, 180, 90]) self.client = MockTileClient() self.source = TiledSource(self.source_grid, self.client) self.image_opts = ImageOptions(format='image/png') self.tile_mgr = TileManager(self.grid, self.file_cache, [self.source], 'png', image_opts=self.image_opts)
def test_merge_rgb_with_transp(self): img1 = ImageSource(Image.new('RGB', (10, 10), (255, 0, 255))) raw = Image.new('RGB', (10, 10), (0, 255, 255)) raw.info = {'transparency': (0, 255, 255)} # make full transparent img2 = ImageSource(raw) result = merge_images([img1, img2], ImageOptions(transparent=False)) img = result.as_image() eq_(img.getpixel((0, 0)), (255, 0, 255))
def test_simple_resize_nearest(self): bbox = (-10, -5, 30, 35) transformer = ImageTransformer(SRS(4326), SRS(4326)) result = transformer.transform(self.img, bbox, (200, 200), bbox, image_opts=ImageOptions(resampling='nearest')) img = result.as_image() eq_(img.size, (200, 200)) eq_(len(img.getcolors()), 2)
def test_output_formats_greyscale_alpha_png(self): img = Image.new("LA", (100, 100)) ir = ImageSource(img, image_opts=PNG_FORMAT) img = Image.open( ir.as_buffer( ImageOptions(colors=256, transparent=True, format="image/png"))) assert img.mode == "LA" assert img.getpixel((0, 0)) == (0, 0)
def test_outside(self): sub_img = create_image((50, 50), color=[100, 120, 130, 140]) img = SubImageSource( sub_img, size=(100, 100), offset=(200, 0), image_opts=ImageOptions(transparent=True), ).as_image() assert img.getcolors() == [(100 * 100, (255, 255, 255, 0))]
def test_mask_partial_image_bgcolor(self): img = ImageSource(Image.new('RGB', (100, 100), color=(100, 0, 200)), image_opts=ImageOptions(bgcolor=(200, 30, 120))) result = mask_image_source_from_coverage(img, [0, 0, 10, 10], SRS(4326), coverage([5, 5, 30, 30])) eq_(result.as_image().getcolors(), [(7500, (200, 30, 120)), (2500, (100, 0, 200))])
def get_map(self, query): bbox = query.bbox w = bbox[2] - bbox[0] h = bbox[3] - bbox[1] res_x = w/query.size[0] res_y = h/query.size[1] debug_info = "bbox: %r\nres: %.8f(%.8f)" % (bbox, res_x, res_y) return message_image(debug_info, size=query.size, image_opts=ImageOptions(transparent=True))
def test_one(self): self.cleanup_tiles = [create_tmp_image_file((100, 100))] self.tiles = [ImageSource(self.cleanup_tiles[0])] m = TileMerger(tile_grid=(1, 1), tile_size=(100, 100)) img_opts = ImageOptions(transparent=True) result = m.merge(self.tiles, img_opts) img = result.as_image() eq_(img.size, (100, 100)) eq_(img.mode, 'RGBA')
def test_output_formats_png8(self): img = Image.new('RGBA', (100, 100)) ir = ImageSource(img, image_opts=PNG_FORMAT) img = Image.open( ir.as_buffer( ImageOptions(colors=256, transparent=True, format='image/png'))) assert img.mode == 'P' assert img.getpixel((0, 0)) == 255
def empty_response(self): if self.empty_response_as_png: format = 'png' else: format = self.format if not self._empty_tile: img = BlankImageSource(size=self.grid.tile_size, image_opts=ImageOptions(format=format, transparent=True)) self._empty_tile = img.as_buffer().read() return ImageResponse(self._empty_tile, format=format, timestamp=time.time())
def setup(self): self.file_cache = MockFileCache('/dev/null', 'png', lock_dir=tmp_lock_dir) self.grid = TileGrid(SRS(4326), bbox=[-180, -90, 180, 90]) self.source_base = MockSource() self.source_overlay = MockSource() self.image_opts = ImageOptions(format='image/png') self.tile_mgr = TileManager(self.grid, self.file_cache, [self.source_base, self.source_overlay], 'png', image_opts=self.image_opts) self.layer = CacheMapLayer(self.tile_mgr)
def setup(self): self.file_cache = MockFileCache('/dev/null', 'png') self.grid = TileGrid(SRS(4326), bbox=[-180, -90, 180, 90]) self.source = MockSource() self.image_opts = ImageOptions(format='image/png') self.locker = TileLocker(tmp_lock_dir, 10, "id") self.tile_mgr = TileManager(self.grid, self.file_cache, [self.source], 'png', image_opts=self.image_opts, locker=self.locker, )
def test_simple_resize_bilinear(self): bbox = (-10, -5, 30, 35) transformer = ImageTransformer(SRS(4326), SRS(4326)) result = transformer.transform(self.img, bbox, (200, 200), bbox, image_opts=ImageOptions(resampling='bilinear')) img = result.as_image() eq_(img.size, (200, 200)) # some shades of grey with bilinear assert len(img.getcolors()) >= 4
def test_shapely_mask_with_transform_partial_image_transparent(self): img = ImageSource(Image.new('RGB', (100, 100), color=(100, 0, 200)), image_opts=ImageOptions(transparent=True)) p = Polygon([(0, 0), (222000, 0), (222000, 222000), (0, 222000)]) # ~ 2x2 degres result = mask_image_source_from_coverage(img, [0, 0, 10, 10], SRS(4326), coverage(p, 'EPSG:3857')) # 20*20 = 400 assert_img_colors_eq(result.as_image().getcolors(), [(10000-400, (255, 255, 255, 0)), (400, (100, 0, 200, 255))])
def test_bundle_header(self): t = Tile((5000, 1000, 12), ImageSource(BytesIO(b'a' * 4000), image_opts=ImageOptions(format='image/png'))) self.cache.store_tile(t) assert os.path.exists( os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle')) assert os.path.exists( os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundlx')) def assert_header(tile_bytes_written, max_tile_bytes): with open(os.path.join(self.cache_dir, 'L12', 'R0380C1380.bundle'), 'r+b') as f: header = struct.unpack('<lllllllllllllll', f.read(60)) assert header[11] == 896 assert header[12] == 1023 assert header[13] == 4992 assert header[14] == 5119 assert header[6] == 60 + 128 * 128 * 4 + sum( tile_bytes_written) assert header[2] == max_tile_bytes assert header[4] == len(tile_bytes_written) * 4 assert_header([4000 + 4], 4000) t = Tile((5000, 1001, 12), ImageSource(BytesIO(b'a' * 6000), image_opts=ImageOptions(format='image/png'))) self.cache.store_tile(t) assert_header([4000 + 4, 6000 + 4], 6000) t = Tile((4992, 999, 12), ImageSource(BytesIO(b'a' * 1000), image_opts=ImageOptions(format='image/png'))) self.cache.store_tile(t) assert_header([4000 + 4, 6000 + 4, 1000 + 4], 6000) t = Tile((5000, 1001, 12), ImageSource(BytesIO(b'a' * 3000), image_opts=ImageOptions(format='image/png'))) self.cache.store_tile(t) assert_header([4000 + 4, 6000 + 4 + 3000 + 4, 1000 + 4], 6000) # still contains bytes from overwritten tile
def test_single_color_tile_store_w_alpha(self): img = Image.new('RGBA', (256, 256), color='#ff0105') tile = Tile((0, 0, 4), ImageSource(img, image_opts=ImageOptions(format='image/png'))) self.cache.link_single_color_images = True self.cache.store_tile(tile) assert self.cache.is_cached(tile) loc = self.cache.tile_location(tile) assert os.path.islink(loc) assert os.path.realpath(loc).endswith('ff0105ff.png') assert is_png(open(loc, 'rb'))
def render(self, tile_request, use_profiles=None, coverage=None, decorate_img=None): self.requested = True resp = BlankImageSource((256, 256), image_opts=ImageOptions(format='image/png')) resp.timestamp = 0 return resp
def test_mask_partial_image_transparent(self): img = ImageSource(Image.new('RGB', (100, 100), color=(100, 0, 200)), image_opts=ImageOptions(transparent=True)) result = mask_image_source_from_coverage(img, [0, 0, 10, 10], SRS(4326), coverage([5, 5, 30, 30])) assert_img_colors_eq(result.as_image().getcolors(), [(7500, (255, 255, 255, 0)), (2500, (100, 0, 200, 255))])
def test_missing_tiles(self): self.cleanup_tiles = [create_tmp_image_file((100, 100))] self.tiles = [ImageSource(self.cleanup_tiles[0])] self.tiles.extend([None] * 8) m = TileMerger(tile_grid=(3, 3), tile_size=(100, 100)) img_opts = ImageOptions() result = m.merge(self.tiles, img_opts) img = result.as_image() assert img.size == (300, 300) assert img.getcolors() == [(80000, (255, 255, 255)), (10000, (0, 0, 0))]
def tile_mgr(self, file_cache, tile_locker): grid = TileGrid(SRS(4326), bbox=[-180, -90, 180, 90]) client = MockTileClient() source = TiledSource(grid, client) image_opts = ImageOptions(format='image/png') return TileManager(grid, file_cache, [source], 'png', image_opts=image_opts, locker=tile_locker)
def source(self, mock_http_client): req_template = WMS111MapRequest(url='http://localhost/service?', param={ 'format': 'image/png', 'layers': 'foo' }) client = WMSClient(req_template, http_client=mock_http_client) return WMSSource(client, supported_srs=[SRS(4326)], image_opts=ImageOptions(resampling='bilinear'))
def test_merge_L(self): img1 = ImageSource(Image.new('RGBA', (10, 10), (255, 0, 255, 255))) img2 = ImageSource(Image.new('L', (10, 10), 100)) # img2 overlays img1 result = merge_images([img1, img2], ImageOptions(transparent=True)) img = result.as_image() assert_img_colors_eq(img, [ (10 * 10, (100, 100, 100, 255)), ])
def test_full_merge(self): self.cleanup_tiles = [ create_tmp_image_file((100, 100)) for _ in range(9) ] self.tiles = [ImageSource(tile) for tile in self.cleanup_tiles] m = TileMerger(tile_grid=(3, 3), tile_size=(100, 100)) img_opts = ImageOptions() result = m.merge(self.tiles, img_opts) img = result.as_image() eq_(img.size, (300, 300))
def test_overlap_right(self): sub_img = create_image((50, 50), color=[100, 120, 130, 140]) img = SubImageSource( sub_img, size=(100, 100), offset=(75, 25), image_opts=ImageOptions(transparent=True)).as_image() eq_(sorted(img.getcolors()), [(25 * 50, (100, 120, 130, 140)), (100 * 100 - 25 * 50, (255, 255, 255, 0))])
def get_info(self, info_request): if info_request.format != self.format: raise RequestError( 'invalid format (%s). this tile set only supports (%s)' % (info_request.format, self.format), request=info_request, code='InvalidParameterValue') tile_coord = self._internal_tile_coord(info_request) coverage_intersects = False if coverage: tile_bbox = self.grid.tile_bbox(tile_coord) if coverage.contains(tile_bbox, self.grid.srs): pass elif coverage.intersects(tile_bbox, self.grid.srs): coverage_intersects = True else: return self.empty_response() dimensions = self.checked_dimensions(info_request) try: with self.tile_manager.session(): tile = self.tile_manager.load_tile_coord(tile_coord, dimensions=dimensions, with_metadata=True) if tile.source is None: return self.empty_response() # Provide the wrapping WSGI app or filter the opportunity to process the # image before it's wrapped up in a response if decorate_img: tile.source = decorate_img(tile.source) if coverage_intersects: if self.empty_response_as_png: format = 'png' image_opts = ImageOptions(transparent=True, format='png') else: format = self.format image_opts = tile.source.image_opts tile.source = mask_image_source_from_coverage( tile.source, tile_bbox, self.grid.srs, coverage, image_opts) return TileResponse(tile, format=format, image_opts=image_opts) format = None if self._mixed_format else info_request.format return TileResponse(tile, format=format, image_opts=self.tile_manager.image_opts) except SourceError as e: raise RequestError(e.args[0], request=info_request, internal=True)
def concat_legends(legends, format='png', size=None, bgcolor='#ffffff', transparent=True): """ Merge multiple legends into one :param images: list of `ImageSource`, bottom image first :param format: the format of the output `ImageSource` :param size: size of the merged image, if ``None`` the size will be calculated :rtype: `ImageSource` """ if not legends: return BlankImageSource(size=(1,1), image_opts=ImageOptions(bgcolor=bgcolor, transparent=transparent)) if len(legends) == 1: return legends[0] legends = legends[:] legends.reverse() if size is None: legend_width = 0 legend_height = 0 legend_position_y = [] #iterate through all legends, last to first, calc img size and remember the y-position for legend in legends: legend_position_y.append(legend_height) tmp_img = legend.as_image() legend_width = max(legend_width, tmp_img.size[0]) legend_height += tmp_img.size[1] #images shall not overlap themselfs size = [legend_width, legend_height] bgcolor = ImageColor.getrgb(bgcolor) if transparent: img = Image.new('RGBA', size, bgcolor+(0,)) else: img = Image.new('RGB', size, bgcolor) for i in range(len(legends)): legend_img = legends[i].as_image() if legend_img.mode == 'RGBA': # paste w transparency mask from layer img.paste(legend_img, (0, legend_position_y[i]), legend_img) else: img.paste(legend_img, (0, legend_position_y[i])) return ImageSource(img, image_opts=ImageOptions(format=format))
def test_mask_outside_of_image_transparent(self): img = ImageSource( Image.new("RGB", (100, 100), color=(100, 0, 200)), image_opts=ImageOptions(transparent=True), ) result = mask_image_source_from_coverage( img, [0, 0, 10, 10], SRS(4326), coverage([20, 20, 30, 30]) ) assert_img_colors_eq( result.as_image().getcolors(), [((100 * 100), (255, 255, 255, 0))] )
def test_merge_noops(self): """ Check that black image is returned for no ops. """ merger = BandMerger(mode="RGB") img_opts = ImageOptions("RGB") result = merger.merge([self.img0], img_opts) img = result.as_image() assert img.size == (10, 10) assert img.getpixel((0, 0)) == (0, 0, 0)