def merge(self, image_opts, size=None, bbox=None, bbox_srs=None, coverage=None): """ Merge the layers. If the format is not 'png' just return the last image. :param format: The image format for the result. :param size: The size for the merged output. :rtype: `ImageSource` """ if not self.layers: return BlankImageSource(size=size, image_opts=image_opts, cacheable=True) if len(self.layers) == 1: layer_img, layer = self.layers[0] layer_opts = layer_img.image_opts if (((layer_opts and not layer_opts.transparent) or image_opts.transparent) and (not size or size == layer_img.size) and (not layer or not layer.coverage or not layer.coverage.clip) and not coverage): # layer is opaque, no need to make transparent or add bgcolor return layer_img if size is None: size = self.layers[0][0].size cacheable = self.cacheable result = create_image(size, image_opts) for layer_img, layer in self.layers: if not layer_img.cacheable: cacheable = False img = layer_img.as_image() layer_image_opts = layer_img.image_opts if layer and layer.coverage and layer.coverage.clip: img = mask_image(img, bbox, bbox_srs, layer.coverage) if (layer_image_opts and layer_image_opts.opacity is not None and layer_image_opts.opacity < 1.0): img = img.convert(result.mode) result = Image.blend(result, img, layer_image_opts.opacity) else: if img.mode == 'RGBA': # paste w transparency mask from layer result.paste(img, (0, 0), img) else: result.paste(img, (0, 0)) # apply global clip coverage if coverage: bg = create_image(size, image_opts) mask = mask_image(result, bbox, bbox_srs, coverage) bg.paste(result, (0, 0), mask) result = bg return ImageSource(result, size=size, image_opts=image_opts, cacheable=cacheable)
def merge(self, image_opts, size=None, bbox=None, bbox_srs=None, coverage=None): """ Merge the layers. If the format is not 'png' just return the last image. :param format: The image format for the result. :param size: The size for the merged output. :rtype: `ImageSource` """ if not self.layers: return BlankImageSource(size=size, image_opts=image_opts, cacheable=True) if len(self.layers) == 1: layer_img, layer = self.layers[0] layer_opts = layer_img.image_opts if (((layer_opts and not layer_opts.transparent) or image_opts.transparent) and (not size or size == layer_img.size) and (not layer or not layer.coverage or not layer.coverage.clip)): # layer is opaque, no need to make transparent or add bgcolor return layer_img if size is None: size = self.layers[0][0].size cacheable = self.cacheable result = create_image(size, image_opts) for layer_img, layer in self.layers: if not layer_img.cacheable: cacheable = False img = layer_img.as_image() layer_image_opts = layer_img.image_opts if layer and layer.coverage and layer.coverage.clip: img = mask_image(img, bbox, bbox_srs, layer.coverage) if (layer_image_opts and layer_image_opts.opacity is not None and layer_image_opts.opacity < 1.0): img = img.convert(result.mode) result = Image.blend(result, img, layer_image_opts.opacity) else: if img.mode == 'RGBA': # paste w transparency mask from layer result.paste(img, (0, 0), img) else: result.paste(img, (0, 0)) # apply global clip coverage if coverage: bg = create_image(size, image_opts) mask = mask_image(result, bbox, bbox_srs, coverage) bg.paste(result, (0, 0), mask) result = bg return ImageSource(result, size=size, image_opts=image_opts, cacheable=cacheable)
def test_rgba_bgcolor_rgba_mode(self): img = create_image((100, 100), ImageOptions(bgcolor=(200, 100, 0, 30), mode="RGBA")) assert img.size == (100, 100) assert img.mode == "RGBA" assert img.getcolors() == [(100 * 100, (200, 100, 0, 30))]
def test_rgba_bgcolor_rgba_mode(self): img = create_image((100, 100), ImageOptions(bgcolor=(200, 100, 0, 30), mode='RGBA')) eq_(img.size, (100, 100)) eq_(img.mode, 'RGBA') eq_(img.getcolors(), [(100 * 100, (200, 100, 0, 30))])
def test_rgba_bgcolor_transparent(self): img = create_image((100, 100), ImageOptions(bgcolor=(200, 100, 0, 30), transparent=True)) eq_(img.size, (100, 100)) eq_(img.mode, 'RGBA') eq_(img.getcolors(), [(100 * 100, (200, 100, 0, 30))])
def get_tile(self, crop_coord, tile_size): """ Return the cropped tile. :param crop_coord: the upper left pixel coord to start :param tile_size: width and height of the new tile :rtype: `ImageSource` """ minx, miny = crop_coord maxx = minx + tile_size[0] maxy = miny + tile_size[1] if (minx < 0 or miny < 0 or maxx > self.meta_img.size[0] or maxy > self.meta_img.size[1]): crop = self.meta_img.crop(( max(minx, 0), max(miny, 0), min(maxx, self.meta_img.size[0]), min(maxy, self.meta_img.size[1]))) result = create_image(tile_size, self.image_opts) result.paste(crop, (abs(min(minx, 0)), abs(min(miny, 0)))) crop = result else: crop = self.meta_img.crop((minx, miny, maxx, maxy)) return ImageSource(crop, size=tile_size, image_opts=self.image_opts)
def mask_image_source_from_coverage(img_source, bbox, bbox_srs, coverage, image_opts=None): if image_opts is None: image_opts = img_source.image_opts img = img_source.as_image() img = mask_image(img, bbox, bbox_srs, coverage) result = create_image(img.size, image_opts) result.paste(img, (0, 0), img) return ImageSource(result, image_opts=image_opts)
def test_rgba_bgcolor_transparent(self): img = create_image( (100, 100), ImageOptions(bgcolor=(200, 100, 0, 30), transparent=True), ) assert img.size == (100, 100) assert img.mode == "RGBA" assert img.getcolors() == [(100 * 100, (200, 100, 0, 30))]
def SubImageSource(source, size, offset, image_opts, cacheable=True): """ Create a new ImageSource with `size` and `image_opts` and place `source` image at `offset`. """ # force new image to contain alpha channel new_image_opts = image_opts.copy() new_image_opts.transparent = True img = create_image(size, new_image_opts) if not hasattr(source, 'as_image'): source = ImageSource(source) subimg = source.as_image() img.paste(subimg, offset) return ImageSource(img, size=size, image_opts=image_opts, cacheable=cacheable)
def SubImageSource(source, size, offset, image_opts, cacheable=True): """ Create a new ImageSource with `size` and `image_opts` and place `source` image at `offset`. """ # force new image to contain alpha channel new_image_opts = image_opts.copy() new_image_opts.transparent = True img = create_image(size, new_image_opts) if not hasattr(source, 'as_image'): source = ImageSource(source) subimg = source.as_image() img.paste(subimg, offset) return ImageSource(img, size=size, image_opts=new_image_opts, cacheable=cacheable)
def merge(self, ordered_tiles, image_opts): """ Merge all tiles into one image. :param ordered_tiles: list of tiles, sorted row-wise (top to bottom) :rtype: `ImageSource` """ if self.tile_grid == (1, 1): assert len(ordered_tiles) == 1 if ordered_tiles[0] is not None: tile = ordered_tiles.pop() return tile src_size = self._src_size() result = create_image(src_size, image_opts) cacheable = True for i, source in enumerate(ordered_tiles): if source is None: continue try: if not source.cacheable: cacheable = False tile = source.as_image() pos = self._tile_offset(i) tile.draft(image_opts.mode, self.tile_size) result.paste(tile, pos) source.close_buffers() except IOError as e: if e.errno is None: # PIL error log.warning( 'unable to load tile %s, removing it (reason was: %s)' % (source, str(e))) if getattr(source, 'filename'): if os.path.exists(source.filename): os.remove(source.filename) else: raise return ImageSource(result, size=src_size, image_opts=image_opts, cacheable=cacheable)
def merge(self, ordered_tiles, image_opts): """ Merge all tiles into one image. :param ordered_tiles: list of tiles, sorted row-wise (top to bottom) :rtype: `ImageSource` """ if self.tile_grid == (1, 1): assert len(ordered_tiles) == 1 if ordered_tiles[0] is not None: tile = ordered_tiles.pop() return tile src_size = self._src_size() result = create_image(src_size, image_opts) cacheable = True for i, source in enumerate(ordered_tiles): if source is None: continue try: if not source.cacheable: cacheable = False tile = source.as_image() pos = self._tile_offset(i) tile.draft(image_opts.mode, self.tile_size) result.paste(tile, pos) source.close_buffers() except IOError as e: if e.errno is None: # PIL error log.warn('unable to load tile %s, removing it (reason was: %s)' % (source, str(e))) if getattr(source, 'filename'): if os.path.exists(source.filename): os.remove(source.filename) else: raise return ImageSource(result, size=src_size, image_opts=image_opts, cacheable=cacheable)
def get_tile(self, crop_coord, tile_size): """ Return the cropped tile. :param crop_coord: the upper left pixel coord to start :param tile_size: width and height of the new tile :rtype: `ImageSource` """ minx, miny = crop_coord maxx = minx + tile_size[0] maxy = miny + tile_size[1] if (minx < 0 or miny < 0 or maxx > self.meta_img.size[0] or maxy > self.meta_img.size[1]): crop = self.meta_img.crop( (max(minx, 0), max(miny, 0), min(maxx, self.meta_img.size[0]), min(maxy, self.meta_img.size[1]))) result = create_image(tile_size, self.image_opts) result.paste(crop, (abs(min(minx, 0)), abs(min(miny, 0)))) crop = result else: crop = self.meta_img.crop((minx, miny, maxx, maxy)) return ImageSource(crop, size=tile_size, image_opts=self.image_opts)
def test_transparent_rgb(self): img = create_image((100, 100), ImageOptions(mode='RGB', transparent=True)) eq_(img.size, (100, 100)) eq_(img.mode, 'RGB') eq_(img.getcolors(), [(100 * 100, (255, 255, 255))])
def new_image(self, size): return create_image(size, self.image_opts)
def test_rgba_bgcolor_rgba_mode(self): img = create_image((100, 100), ImageOptions(bgcolor=(200, 100, 0, 30), mode='RGBA')) eq_(img.size, (100, 100)) eq_(img.mode, 'RGBA') eq_(img.getcolors(), [(100*100, (200, 100, 0, 30))])
def test_rgba_bgcolor_transparent(self): img = create_image((100, 100), ImageOptions(bgcolor=(200, 100, 0, 30), transparent=True)) eq_(img.size, (100, 100)) eq_(img.mode, 'RGBA') eq_(img.getcolors(), [(100*100, (200, 100, 0, 30))])
def test_bgcolor(self): img = create_image((100, 100), ImageOptions(bgcolor=(200, 100, 0))) eq_(img.size, (100, 100)) eq_(img.mode, 'RGB') eq_(img.getcolors(), [(100*100, (200, 100, 0))])
def test_transparent_rgb(self): img = create_image((100, 100), ImageOptions(mode='RGB', transparent=True)) eq_(img.size, (100, 100)) eq_(img.mode, 'RGB') eq_(img.getcolors(), [(100*100, (255, 255, 255))])
def test_transparent_rgb(self): img = create_image((100, 100), ImageOptions(mode="RGB", transparent=True)) assert img.size == (100, 100) assert img.mode == "RGB" assert img.getcolors() == [(100 * 100, (255, 255, 255))]
def test_default(self): img = create_image((100, 100)) eq_(img.size, (100, 100)) eq_(img.mode, 'RGB') eq_(img.getcolors(), [(100 * 100, (255, 255, 255))])
def merge(self, image_opts, size=None, bbox=None, bbox_srs=None, coverage=None): """ Merge the layers. If the format is not 'png' just return the last image. :param format: The image format for the result. :param size: The size for the merged output. :rtype: `ImageSource` """ if not self.layers: return BlankImageSource(size=size, image_opts=image_opts, cacheable=True) if len(self.layers) == 1: layer_img, layer_coverage = self.layers[0] layer_opts = layer_img.image_opts if (((layer_opts and not layer_opts.transparent) or image_opts.transparent) and (not size or size == layer_img.size) and (not layer_coverage or not layer_coverage.clip) and not coverage): # layer is opaque, no need to make transparent or add bgcolor return layer_img if size is None: size = self.layers[0][0].size cacheable = self.cacheable result = create_image(size, image_opts) for layer_img, layer_coverage in self.layers: if not layer_img.cacheable: cacheable = False img = layer_img.as_image() layer_image_opts = layer_img.image_opts if layer_image_opts is None: opacity = None else: opacity = layer_image_opts.opacity if layer_coverage and layer_coverage.clip: img = mask_image(img, bbox, bbox_srs, layer_coverage) if result.mode != 'RGBA': merge_composite = False else: merge_composite = has_alpha_composite_support() if 'transparency' in img.info: # non-paletted PNGs can have a fixed transparency value # convert to RGBA to have full alpha img = img.convert('RGBA') if merge_composite: if opacity is not None and opacity < 1.0: # fade-out img to add opacity value img = img.convert("RGBA") alpha = img.split()[3] alpha = ImageChops.multiply( alpha, ImageChops.constant(alpha, int(255 * opacity))) img.putalpha(alpha) if img.mode in ('RGBA', 'P'): # assume paletted images have transparency if img.mode == 'P': img = img.convert('RGBA') result = Image.alpha_composite(result, img) else: result.paste(img, (0, 0)) else: if opacity is not None and opacity < 1.0: img = img.convert(result.mode) result = Image.blend(result, img, layer_image_opts.opacity) elif img.mode in ('RGBA', 'P'): # assume paletted images have transparency if img.mode == 'P': img = img.convert('RGBA') # paste w transparency mask from layer result.paste(img, (0, 0), img) else: result.paste(img, (0, 0)) # apply global clip coverage if coverage: bg = create_image(size, image_opts) mask = mask_image(result, bbox, bbox_srs, coverage) bg.paste(result, (0, 0), mask) result = bg return ImageSource(result, size=size, image_opts=image_opts, cacheable=cacheable)
def as_image(self): if not self._img: self._img = create_image(self.size, self.image_opts) return self._img
def test_merge_composite(self): img = create_image((100, 100), ImageOptions(merge='composite')) eq_(img.mode, 'RGBA')
def test_default(self): img = create_image((100, 100)) assert img.size == (100, 100) assert img.mode == "RGB" assert img.getcolors() == [(100 * 100, (255, 255, 255))]
def test_bgcolor(self): img = create_image((100, 100), ImageOptions(bgcolor=(200, 100, 0))) eq_(img.size, (100, 100)) eq_(img.mode, 'RGB') eq_(img.getcolors(), [(100 * 100, (200, 100, 0))])
def test_default(self): img = create_image((100, 100)) eq_(img.size, (100, 100)) eq_(img.mode, 'RGB') eq_(img.getcolors(), [(100*100, (255, 255, 255))])
def merge(self, image_opts, size=None, bbox=None, bbox_srs=None, coverage=None): """ Merge the layers. If the format is not 'png' just return the last image. :param format: The image format for the result. :param size: The size for the merged output. :rtype: `ImageSource` """ if not self.layers: return BlankImageSource(size=size, image_opts=image_opts, cacheable=True) if len(self.layers) == 1: layer_img, layer = self.layers[0] layer_opts = layer_img.image_opts if (((layer_opts and not layer_opts.transparent) or image_opts.transparent) and (not size or size == layer_img.size) and (not layer or not layer.coverage or not layer.coverage.clip) and not coverage): # layer is opaque, no need to make transparent or add bgcolor return layer_img if size is None: size = self.layers[0][0].size cacheable = self.cacheable result = create_image(size, image_opts) for layer_img, layer in self.layers: if not layer_img.cacheable: cacheable = False img = layer_img.as_image() layer_image_opts = layer_img.image_opts if layer_image_opts is None: opacity = None else: opacity = layer_image_opts.opacity if layer and layer.coverage and layer.coverage.clip: img = mask_image(img, bbox, bbox_srs, layer.coverage) if result.mode != 'RGBA': merge_composite = False else: merge_composite = has_alpha_composite_support() if merge_composite: if opacity is not None and opacity < 1.0: # fade-out img to add opacity value img = img.convert("RGBA") alpha = img.split()[3] alpha = ImageChops.multiply( alpha, ImageChops.constant(alpha, int(255 * opacity)) ) img.putalpha(alpha) if img.mode in ('RGBA', 'P'): # assume paletted images have transparency if img.mode == 'P': img = img.convert('RGBA') result = Image.alpha_composite(result, img) else: result.paste(img, (0, 0)) else: if opacity is not None and opacity < 1.0: img = img.convert(result.mode) result = Image.blend(result, img, layer_image_opts.opacity) elif img.mode in ('RGBA', 'P'): # assume paletted images have transparency if img.mode == 'P': img = img.convert('RGBA') # paste w transparency mask from layer result.paste(img, (0, 0), img) else: result.paste(img, (0, 0)) # apply global clip coverage if coverage: bg = create_image(size, image_opts) mask = mask_image(result, bbox, bbox_srs, coverage) bg.paste(result, (0, 0), mask) result = bg return ImageSource(result, size=size, image_opts=image_opts, cacheable=cacheable)
def test_bgcolor(self): img = create_image((100, 100), ImageOptions(bgcolor=(200, 100, 0))) assert img.size == (100, 100) assert img.mode == "RGB" assert img.getcolors() == [(100 * 100, (200, 100, 0))]