def draw_pattern(draw, size): w, h = size black_color = ImageColor.getrgb("black") draw.rectangle((0, 0, w - 1, h - 1), outline=black_color) draw.ellipse((0, 0, w - 1, h - 1), outline=black_color) step = w / 16.0 for i in range(16): color = ImageColor.getrgb('#3' + hex(16 - i)[-1] + hex(i)[-1]) draw.line((i * step, 0, i * step, h), fill=color) step = h / 16.0 for i in range(16): color = ImageColor.getrgb('#' + hex(16 - i)[-1] + hex(i)[-1] + '3') draw.line((0, i * step, w, i * step), fill=color)
def draw_pattern(draw, size): w, h = size black_color = ImageColor.getrgb("black") draw.rectangle((0, 0, w-1, h-1), outline=black_color) draw.ellipse((0, 0, w-1, h-1), outline=black_color) step = w/16.0 for i in range(16): color = ImageColor.getrgb('#3' + hex(16-i)[-1] + hex(i)[-1]) draw.line((i*step, 0, i*step, h), fill=color) step = h/16.0 for i in range(16): color = ImageColor.getrgb('#' + hex(16-i)[-1] + hex(i)[-1] + '3') draw.line((0, i*step, w, i*step), fill=color)
def create_image(size, image_opts=None): """ Create a new image that is compatible with the given `image_opts`. Takes into account mode, transparent, bgcolor. """ from mapproxy.platform.image import Image, ImageColor if image_opts is None: mode = 'RGB' bgcolor = (255, 255, 255) else: mode = image_opts.mode if mode in (None, 'P'): if image_opts.transparent: mode = 'RGBA' else: mode = 'RGB' bgcolor = image_opts.bgcolor or (255, 255, 255) if isinstance(bgcolor, basestring): bgcolor = ImageColor.getrgb(bgcolor) if image_opts.transparent and len(bgcolor) == 3: bgcolor = bgcolor + (0, ) if image_opts.mode == 'I': bgcolor = bgcolor[0] return Image.new(mode, size, bgcolor)
def create_debug_img(size, transparent=True): if transparent: img = Image.new("RGBA", size) else: img = Image.new("RGB", size, ImageColor.getrgb("#EEE")) draw = ImageDraw.Draw(img) draw_pattern(draw, size) return img
def create_tmp_image_file(size, two_colored=False): fd, out_file = tempfile.mkstemp(suffix=".png") os.close(fd) print "creating temp image %s (%r)" % (out_file, size) img = Image.new("RGBA", size) if two_colored: draw = ImageDraw.Draw(img) draw.rectangle((0, 0, img.size[0] // 2, img.size[1]), fill=ImageColor.getrgb("white")) img.save(out_file, "png") return out_file
def test_blank(self): image_opts = PNG_FORMAT.copy() image_opts.bgcolor = '#113399' img = message_image('', size=(100, 150), image_opts=image_opts) assert isinstance(img, ImageSource) eq_(img.size, (100, 150)) pil_img = img.as_image() eq_(pil_img.getpixel((0, 0)), ImageColor.getrgb('#113399')) # 3 values in histogram (RGB) assert [x for x in pil_img.histogram() if x > 0] == [15000, 15000, 15000]
def create_tmp_image_file(size, two_colored=False): fd, out_file = tempfile.mkstemp(suffix='.png') os.close(fd) print 'creating temp image %s (%r)' % (out_file, size) img = Image.new('RGBA', size) if two_colored: draw = ImageDraw.Draw(img) draw.rectangle((0, 0, img.size[0]//2, img.size[1]), fill=ImageColor.getrgb('white')) img.save(out_file, 'png') return out_file
def create_tmp_image_file(size, two_colored=False): fd, out_file = tempfile.mkstemp(suffix='.png') os.close(fd) print 'creating temp image %s (%r)' % (out_file, size) img = Image.new('RGBA', size) if two_colored: draw = ImageDraw.Draw(img) draw.rectangle((0, 0, img.size[0] // 2, img.size[1]), fill=ImageColor.getrgb('white')) img.save(out_file, 'png') return out_file
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 create_mixed_mode_img(size, format='png'): img = Image.new("RGBA", size) # draw a black rectangle into the image, rect_width = 3/4 img_width # thus 1/4 of the image is transparent and with square tiles, one of two # tiles (img size = 512x256) will be fully opaque and the other # has transparency draw = ImageDraw.Draw(img) w, h = size red_color = ImageColor.getrgb("red") draw.rectangle((w/4, 0, w, h), fill=red_color) data = StringIO() img.save(data, format) data.seek(0) yield data
def create_mixed_mode_img(size, format='png'): img = Image.new("RGBA", size) # draw a black rectangle into the image, rect_width = 3/4 img_width # thus 1/4 of the image is transparent and with square tiles, one of two # tiles (img size = 512x256) will be fully opaque and the other # has transparency draw = ImageDraw.Draw(img) w, h = size red_color = ImageColor.getrgb("red") draw.rectangle((w / 4, 0, w, h), fill=red_color) data = StringIO() img.save(data, format) data.seek(0) yield data
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 font_color(self): if self.inverse: return ImageColor.getrgb('white') else: return ImageColor.getrgb('black')
def font_color(self): if self.image_opts.transparent: return ImageColor.getrgb('black') if _luminance(ImageColor.getrgb(self.image_opts.bgcolor)) < 128: return ImageColor.getrgb('white') return ImageColor.getrgb('black')
class MessageImage(object): """ Base class for text rendering in images (for watermarks, exception images, etc.) :ivar font_name: the font name for the text :ivar font_size: the font size of the text :ivar font_color: the color of the font as a tuple :ivar box_color: the color of the box behind the text. color as a tuple or ``None`` """ font_name = 'DejaVu Sans Mono' font_size = 10 font_color = ImageColor.getrgb('black') box_color = None linespacing = 5 padding = 3 placement = 'ul' def __init__(self, message, image_opts): self.message = message self.image_opts = image_opts self._font = None @property def font(self): global _pil_ttf_support if self._font is None: if self.font_name != 'default' and _pil_ttf_support: try: self._font = ImageFont.truetype(font_file(self.font_name), self.font_size) except ImportError: _pil_ttf_support = False log_system.warn( "Couldn't load TrueType fonts, " "PIL needs to be build with freetype support.") except IOError: _pil_ttf_support = False log_system.warn("Couldn't load find TrueType font ", self.font_name) if self._font is None: self._font = ImageFont.load_default() return self._font def new_image(self, size): return Image.new('RGBA', size) def draw(self, img=None, size=None, in_place=True): """ Create the message image. Either draws on top of `img` or creates a new image with the given `size`. """ if not ((img and not size) or (size and not img)): raise TypeError, 'need either img or size argument' if img is None: base_img = self.new_image(size) elif not in_place: size = img.size base_img = self.new_image(size) else: base_img = img.as_image() size = base_img.size if not self.message: if img is not None: return img return ImageSource(base_img, size=size, image_opts=self.image_opts) draw = ImageDraw.Draw(base_img) self.draw_msg(draw, size) image_opts = self.image_opts if not in_place and img: image_opts = image_opts or img.image_opts img = img.as_image() converted = False if len(self.font_color) == 4 and img.mode != 'RGBA': # we need RGBA to keep transparency from text converted = img.mode img = img.convert('RGBA') img.paste(base_img, (0, 0), base_img) if converted == 'RGB': # convert image back img = img.convert('RGB') base_img = img return ImageSource(base_img, size=size, image_opts=image_opts) def draw_msg(self, draw, size): td = TextDraw(self.message, font=self.font, bg_color=self.box_color, font_color=self.font_color, placement=self.placement, linespacing=self.linespacing, padding=self.padding) td.draw(draw, size)