# -*- coding:utf8 -*-
from __future__ import division
# import PngImagePlugin
from PIL import Image
from PIL import ImageDraw, ImageChops, ImageColor
from StringIO import StringIO
import OlexVFS
import RoundedCorners
import colorsys
from olexFunctions import OlexFunctions
from FontInstances import FontInstances
OV = OlexFunctions()
import os
global sizedraw
sizedraw_dummy_draw = ImageDraw.Draw(Image.new('RGBA', (300, 300)))
import olx
import math
#debug = bool(OV.GetParam('olex2.debug',False))
debug = False
global dpi_scale
global dpi_scaling
if OV.HasGUI():
import olex_gui
dpi_scale = olex_gui.GetPPI()[0]/96
else:
dpi_scale = 1
dpi_scaling = OV.GetParam('gui.dpi_scaling')
# self.params.html.highlight_colour.rgb = self.params.html.highlight_colour.rgb
# self.params.timage.colour.rgb = self.params.timage.colour.rgb
# self.params.html.bg_colour.rgb = self.params.html.bg_colour.rgb
# self.params.html.table_bg_colour.rgb = self.params.html.table_bg_colour.rgb
# self.params.html.font_colour.rgb = self.params.html.font_colour.rgb
# self.params.logo_colour.rgb = self.params.logo_colour.rgb
# self.params.html.link_colour.rgb = self.params.html.link_colour.rgb
# self.params.html.input_bg_colour.rgb = self.params.html.input_bg_colour.rgb
# self.params.html.base_colour.rgb = self.params.html.base_colour.rgb
# self.params.html.table_firstcol_colour.rgb = self.params.html.table_firstcol_colour.rgb
# self.params.button_colouring.rgb = self.params.button_colouring.rgb
# self.params.grey.rgb = self.params.grey.rgb
# self.params.green.rgb = self.params.green.rgb
# self.params.red.rgb = self.params.red.rgb
class ImageTools(FontInstances):
def __init__(self):
from PIL import ImageColor
super(ImageTools, self).__init__()
self.colorsys = colorsys
self.abort = False
self.getOlexVariables()
self.scale = None
# #Encodings
self.good_encodings = ["ISO8859-1", "ISO8859-2"]
self.gui_language_encoding = olx.CurrentLanguageEncoding()
if OV.HasGUI():
self.gui_current_language = olx.CurrentLanguage()
else:
self.gui_current_language = u'English'
self.get_font_peculiarities()
font = "Verdana"
self.gui_timage_font_name = "%s" % font
self.gui_tab_font_name = "%s Bold" % font
self.gui_sNumTitle_font_name = "%s Bold" % font
self.gui_button_font_name = "%s Bold" % font
self.params = OV.GuiParams()
if olx.HasGUI() == "false":
self.available_width = 200
self.available_width_full = 200
else:
# self.get_available_width()
self.css = OV.GuiParams().css
self.dpi_scale=None
self.im_cache = {}
def get_available_width(self):
global dpi_scale
global dpi_scaling
dpi_scaling = OV.GetParam('gui.dpi_scaling')
if dpi_scaling:
w = OV.GetParam('gui.skin.base_width')
else:
w = olx.html.ClientWidth('self')
self.skin_width = w
self.skin_width_margin = w - OV.GetParam('gui.htmlpanelwidth_margin_adjust')
self.skin_width_table = self.skin_width_margin - OV.GetParam('gui.html.table_firstcol_width')
self.history_width = self.skin_width_table - int(OV.GetParam('gui.html.table_firstcol_width'))
self.max_width = w
self.skin_width = self.skin_width_margin
if OV.HasGUI():
client_width = int(olx.html.ClientWidth('self'))
else:
client_width = 800
self.dpi_scale = (client_width-OV.GetParam('gui.htmlpanelwidth_margin_adjust'))/self.skin_width
if debug:
print("====== dpi_scaling set to %s ======" %self.dpi_scale)
def drawSpaceGroupInfo(self, draw, luminosity=1.9, right_margin=12, font_name="Times Bold", font_colour=None):
base_colour = OV.GetParam('gui.html.base_colour').rgb
left_start = 120
if not font_colour:
font_colour = OV.GetParam('gui.html.font_colour').rgb
self.width = self.skin_width_margin
try:
txt_l = []
txt_sub = []
txt_norm = []
try:
txt = OV.olex_function('sg(%h)')
except:
pass
if not txt:
txt = "ERROR"
txt = txt.replace(" 1", "")
txt = txt.replace(" ", "")
txt_l = txt.split("")
if len(txt_l) == 1:
txt_norm = [(txt, 0)]
try:
font_base = "Times"
font_bar = self.registerFontInstance("%s Bold" % font_base, 11)
font_slash = self.registerFontInstance("%s Bold" % font_base, 18)
font_number = self.registerFontInstance("%s Bold" % font_base, 14)
font_letter = self.registerFontInstance("%s Bold Italic" % font_base, 15)
font_sub = self.registerFontInstance("%s Bold" % font_base, 10)
norm_kern = 2
sub_kern = 0
except:
font_name = "Arial"
font_bar = self.registerFontInstance("%s Bold" % font_base, 12)
font_slash = self.registerFontInstance("%s Bold" % font_base, 18)
font_number = self.registerFontInstance("%s Bold" % font_base, 14)
font_letter = self.registerFontInstance("%s Bold Italic" % font_base, 15)
font_norm = self.registerFontInstance(font_name, 13)
font_sub = self.registerFontInstance(font_name, 10)
norm_kern = 0
sub_kern = 0
textwidth = 0
for item in txt_l:
if item:
try:
sub = item.split("")[1]
except:
sub = ""
norm = item.split("")[0]
tw_s = (draw.textsize(sub, font=font_sub)[0]) + sub_kern
tw_n = (draw.textsize(norm, font=font_number)[0]) + norm_kern
txt_sub.append((sub, tw_s))
txt_norm.append((norm, tw_n))
textwidth += (tw_s + tw_n)
except:
txt_l = []
if txt_l:
i = 0
left_start = (self.width - textwidth) - right_margin - 5
cur_pos = left_start
advance = 0
after_kern = 0
for item in txt_l:
if item:
text_normal = txt_norm[i][0]
for character in text_normal:
if character == "":
continue
cur_pos += advance
cur_pos += after_kern
after_kern = 2
advance = 0
try:
int(character)
font = font_number
top = 0
after_kern = 2
except:
font = font_letter
top = -1
if character == "P" or character == "I" or character == "C":
norm_kern = -2
after_kern = 0
character = " %s" % character
if character == "-":
draw.text((cur_pos + 1, -10), "_", font=font_bar, fill=font_colour)
draw.text((cur_pos + 1, -9), "_", font=font_bar, fill=font_colour)
advance = -1
norm_kern = 0
elif character == "/":
norm_kern = 0
after_kern = 0
draw.text((cur_pos - 2, -3), "/", font=font_slash, fill=font_colour)
advance = ((draw.textsize("/", font=font_slash)[0]) + norm_kern) - 1
else:
draw.text((cur_pos + norm_kern, top), "%s" % character, font=font, fill=font_colour)
advance = (draw.textsize(character, font=font)[0]) + norm_kern
text_in_superscript = txt_sub[i][0]
if text_in_superscript:
cur_pos += advance
draw.text((cur_pos + sub_kern, 5), "%s" % text_in_superscript, font=font_sub, fill=font_colour)
advance = (draw.textsize(text_in_superscript, font=font_sub)[0]) + sub_kern
after_kern = -2
cur_pos += advance
i += 1
def show_image(self, IM):
import sys
sys.path.append("C:\Users\Horst\Documents\olex-trunk\Python26\Lib\site-packages\wx-2.8-msw-unicode")
import wx
a = wx.PySimpleApp()
wximg = wx.Image('%s/splash.jpg' % OV.BaseDir(), wx.BITMAP_TYPE_JPEG)
wxbmp = wx.BitmapFromImage(wximg)
f = wx.Frame(None, -1, "Show JPEG demo")
f.SetSize(wxbmp.GetSize())
wx.StaticBitmap(f, -1, wxbmp, (0, 0))
f.Show(True)
def callback(evt, a=a, f=f):
# Closes the window upon any keypress
f.Close()
a.ExitMainLoop()
wx.EVT_CHAR(f, callback)
a.MainLoop()
def get_unicode_characters(self, txt):
txt = txt.replace("two_theta", "2theta")
txt = txt.replace("stol", "(sin(theta)/lambda)")
txt = txt.replace("_sq", "^2")
txt = txt.replace("_star", "*")
txt = txt.replace("_", " ")
txt = txt.replace("lambda", unichr(61548))
txt = txt.replace("theta", unichr(61553))
txt = txt.replace("Theta", unichr(61553))
txt = txt.replace("sigma", unichr(61555))
txt = txt.replace("^2", unichr(178))
txt = txt.replace("^3", unichr(179))
txt = txt.replace(">", unichr(61681))
txt = txt.replace("<", unichr(61665))
txt = txt.replace("Fo2", "Fo%s" % (unichr(178)))
txt = txt.replace("Fc2", "Fc%s" % (unichr(178)))
txt = txt.replace("Sum", unichr(8721))
# txt = txt.replace("Fexp2", "Fexp%s" %(unichr(178)))
# txt = txt.replace("Fo2", "F%s%s" %(unichr(2092),unichr(178)))
txt = txt.replace("Fexp", "F%s" % (unichr(2091)))
txt = txt.replace("Angstrom", unichr(197))
txt = txt.replace("degrees", u"\u00B0")
return txt
def centre_text(self, draw, txt, font, maxWidth):
txt_size = draw.textsize(txt, font=font)
hStart = self.txt_left + int((maxWidth - txt_size[0]) / 2)
return hStart
def align_text(self, draw, txt, font, maxWidth, align):
if align == "centre":
txt_size = draw.textsize(txt, font=font)
hStart = int((maxWidth - txt_size[0]) / 2)
retVal = hStart
if align == "right":
txt_size = draw.textsize(txt, font=font)
hStart = int((maxWidth - txt_size[0]))
retVal = hStart
return retVal
def decimalColorToHTMLcolor(self, dec_colour):
val = hex(dec_colour)
val = val.lstrip('0x')
if len(val) == 9:
val = val[:6]
elif len(val) > 6:
return dec_colour
w_counter = 0
while len(val) != 6 and w_counter < 1000:
w_counter += 1
val = "0" + val
retVal = "#"
retVal += val[-2:]
retVal += val[-4:-2]
retVal += val[-6:-4]
return retVal
def getOlexVariables(self):
# self.encoding = self.test_encoding(self.gui_language_encoding) ##Language
# self.language = "English" ##Language
# if olx.IsCurrentLanguage('Chinese') == "true":
# self.language = 'Chinese'
self.fonts = self.defineFonts()
self.gui_red = OV.GetParam('gui.red').rgb
self.gui_green = OV.GetParam('gui.green').rgb
self.gui_blue = OV.GetParam('gui.blue').rgb
self.gui_grey = OV.GetParam('gui.grey').rgb
def dec2hex(self, n):
"""return the hexadecimal string representation of integer n"""
return "%X" % n
def hex2dec(self, s):
"""return the integer value of a hexadecimal string s"""
l = list(s)
c = "%s%s%s%s%s%s" % (l[5], l[6], l[3], l[4], l[1], l[2])
return int(c, 16)
def RGBToHTMLColor(self, rgb_tuple):
""" convert an (R, G, B) tuple to #RRGGBB """
hexcolor = '#%02x%02x%02x' % rgb_tuple
# that's it! '%02x' means zero-padded, 2-digit hex values
return hexcolor
def HTMLColorToRGB(self, colorstring):
""" convert #RRGGBB to an (R, G, B) tuple """
try:
colorstring = colorstring.strip()
except:
return colorstring
if colorstring[0] == '#': colorstring = colorstring[1:]
if len(colorstring) != 6:
raise ValueError, "input #%s is not in #RRGGBB format" % colorstring
r, g, b = colorstring[:2], colorstring[2:4], colorstring[4:]
r, g, b = [int(n, 16) for n in (r, g, b)]
return (r, g, b)
def watermark(self, im, mark, position, opacity=1):
"""Adds a watermark to an image."""
if opacity < 1:
mark = self.reduce_opacity(mark, opacity)
if im.mode != 'RGBA':
im = im.convert('RGBA')
# create a transparent layer the size of the image and draw the
# watermark in that layer.
layer = Image.new('RGBA', im.size, (0, 0, 0, 0))
if position == 'tile':
for y in range(0, im.size[1], mark.size[1]):
for x in range(0, im.size[0], mark.size[0]):
layer.paste(mark, (x, y))
elif position == 'scale':
# scale, but preserve the aspect ratio
ratio = min(
float(im.size[0]) / mark.size[0], float(im.size[1]) / mark.size[1])
w = int(mark.size[0] * ratio)
h = int(mark.size[1] * ratio)
mark = mark.resize((w, h))
layer.paste(mark, ((im.size[0] - w) / 2, (im.size[1] - h) / 2))
else:
layer.paste(mark, position)
# composite the watermark with the layer
return Image.composite(layer, im, layer)
def makeBackgroundTransparent(self, img, col=(255, 255, 255)):
col = self.HTMLColorToRGB(col)
img = img.convert("RGBA")
pixdata = img.load()
for y in xrange(img.size[1]):
for x in xrange(img.size[0]):
if pixdata[x, y] == (255, 255, 255, 255):
pixdata[x, y] = (255, 255, 255, 0)
return img
def makeTransparentText(self, im, txt, top_left=(1, 0), font_colour="#000000", font_name="Arial Bold", font_size=14):
# Make a grayscale image of the font, white on black.
font_file = self.fonts[font_name]
imtext = Image.new("L", im.size, 0)
alpha = Image.new("L", im.size, "Black")
drtext = ImageDraw.Draw(imtext)
font = ImageFont.truetype(font_file, font_size)
drtext.text(top_left, txt, font=font, fill="white")
# Add the white text to our collected alpha channel. Gray pixels around
# the edge of the text will eventually become partially transparent
# pixels in the alpha channel.
alpha = ImageChops.lighter(alpha, imtext)
# Make a solid color, and add it to the color layer on every pixel
# that has even a little bit of alpha showing.
solidcolor = Image.new("RGBA", im.size, font_colour)
immask = Image.eval(imtext, lambda p: 255 * (int(p != 0)))
im = Image.composite(solidcolor, im, immask)
im.putalpha(alpha)
return im
def make_colour_pixel(self, colour):
if not colour:
return
size = (10, 10)
IM = Image.new('RGBA', size, colour)
name = r"pixel_%s.png" % colour[1:]
OlexVFS.save_image_to_olex(IM, name, 2)
return name
def make_colour_sample(self, colour, size=(20, 12)):
if not colour:
return
IM = Image.new('RGBA', size, colour)
draw = ImageDraw.Draw(IM)
draw.rectangle((0, 0, IM.size[0] - 1, IM.size[1] - 1), outline='#bcbcbc')
name = r"colour_%s.png" % colour[1:]
OlexVFS.save_image_to_olex(IM, name, 2)
return name
def set_htmlpanel_width(self, new_width):
if not new_width:
return
new_width = float(new_width)
#if dpi_scaling:
#new_width = int(round(new_width*dpi_scale))
if OV.HasGUI():
if new_width <=1:
olx.HtmlPanelWidth("%i %%" %int(new_width*100))
else:
olx.HtmlPanelWidth(new_width)
self.get_available_width()
if debug:
print("============== resized panel to %s, using dpi_scaling: %s ==============" %(new_width, repr(dpi_scaling)))
print("---- IT.max_width = %s" %IT.max_width)
print("---- gui.htmlpanelwidth = %s" %OV.GetParam('gui.htmlpanelwidth'))
print("---- gui.skin.base_width = %s" %OV.GetParam('gui.skin.base_width'))
print("---- self.dpi_scale = %s" %IT.dpi_scale)
print("======================================================")
def resize_image(self, image, size, name=None):
if not self.dpi_scale:
self.get_available_width()
s = self.dpi_scale
if dpi_scaling:
width = int(size[0] * s)
height = int(size[1] * s)
else:
width = int(size[0])
height = int(size[1])
if name:
cache_name = "%s_%s" %(name, width)
_ = self.im_cache.get(cache_name,None)
if _:
if repr(width) in cache_name:
if debug:
print "--- Return %s from Cache!" %name
return _
image = image.resize((width,height), Image.ANTIALIAS)
if debug:
print "+++ Resize %s (%s)!" %(name, s)
if name:
self.im_cache[cache_name] = image
return image
def resize_skin_logo(self, width):
logopath = "%s/%s" % (self.basedir, OV.GetParam('gui.skin.logo_name'))
name = r"skin_logo.png"
if os.path.exists(logopath):
im = Image.open(logopath)
factor = im.size[0] / width
height = int(im.size[1] / factor)
im = self.resize_image(im, (width, height), name=name)
OlexVFS.save_image_to_olex(im, name, 2)
txt = ''
else:
txt = " "
OlexVFS.write_to_olex('logo1_txt.htm', txt, 2)
return "Done"
def resize_to_panelwidth(self, args, width_adjust=0, width=None):
import olex
do_cache_image = True
name = args['i']
im = None
if name.endswith("@vfs"): # name_tmp@vfs
do_cache_image = False
name = name[:-4]
s = OlexVFS.read_from_olex(name)
olex.writeImage(name, "")
name = name[:-4]
sio = StringIO(s)
if not sio.len: # resize was called twice in a raw
return
im = Image.open(sio)
else:
path = ("%s/etc/%s" % (self.basedir, name))
if os.path.exists(path):
im = Image.open(path)
name = name[:-4]
colourize = args.get('c', False)
if not width:
#width = int(olx.html.ClientWidth('self')) - OV.GetParam('gui.htmlpanelwidth_margin_adjust')
width = int(IT.skin_width*0.97)
if im:
if colourize:
im = self.colourize(im, (0, 0, 0), OV.GetParam('gui.logo_colour'))
width = int(width) - width_adjust
if width < 10: return
factor = im.size[0] / width
height = int(im.size[1] / factor)
if do_cache_image:
im = self.resize_image(im, (width, height), name=name)
else:
im = self.resize_image(im, (width, height))
OlexVFS.save_image_to_olex(im, name, 2)
else:
pass
return "Done"
def reduce_opacity(self, im, opacity):
"""Returns an image with reduced opacity."""
from PIL import ImageEnhance
assert opacity >= 0 and opacity <= 1
if im.mode != 'RGBA':
im = im.convert('RGBA')
else:
im = im.copy()
alpha = im.split()[3]
alpha = ImageEnhance.Brightness(alpha).enhance(opacity)
im.putalpha(alpha)
return im
def doDup(self, image, offset_x=1, offset_y=1, blend=0.1):
dup = ImageChops.duplicate(image)
dup = ImageChops.invert(dup)
dup = ImageChops.offset(dup, offset_x, offset_y)
image = ImageChops.blend(image, dup, blend)
return image
def add_vline(self, draw, height, h_pos, v_pos, weight=1, colour=(237, 237, 235)):
begin = (h_pos, v_pos)
end = (h_pos, height)
draw.line((begin , end), fill=self.adjust_colour(colour, luminosity=1))
pass
def add_whitespace(self, image, side, weight, colour, margin_left=0, margin_right=0, margin_top=0, margin_bottom=0, overwrite=False):
weight = int(weight)
width, height = image.size
top = 0 + margin_top
left = 0 + margin_left
bottom = height - margin_bottom
right = width - margin_right
if overwrite:
weight_add = 0
else:
weight_add = weight
if side == "top":
whitespace = Image.new('RGBA', (width - margin_left - margin_right, weight), colour)
canvas = Image.new('RGBA', (width, height + weight_add), colour)
canvas.paste(whitespace, (margin_left, 0))
canvas.paste(image, (0, weight))
elif side == "bottom":
whitespace = Image.new('RGBA', (width - margin_left - margin_right, weight), colour)
canvas = Image.new('RGBA', (width, height + weight_add), colour)
canvas.paste(whitespace, (margin_left, height - weight + margin_top))
canvas.paste(image, (0, 0))
elif side == "right":
whitespace = Image.new('RGBA', (weight, height - margin_top - margin_bottom), colour)
canvas = Image.new('RGBA', (width + weight_add, height), colour)
canvas.paste(image, (0, 0))
canvas.paste(whitespace, (width - weight + weight_add, margin_top))
elif side == "left":
whitespace = Image.new('RGBA', (weight, height - margin_top - margin_bottom), colour)
canvas = Image.new('RGBA', (width + weight_add, height), colour)
canvas.paste(whitespace, (0, margin_top))
canvas.paste(image, (weight, 0))
return canvas
def cut_image(self, image, cuts=(10, 20)):
''' Returns a list of images, cut left to right at the cuts positions '''
retVal = []
size = image.size
current = 0
for cut in cuts:
left = 0
right = cut
current += right
retVal.append(image.crop((left, 0, right, size[1])))
retVal.append(image.crop((current, 0, size[0], size[1])))
return retVal
def colourize(self, IM, col_1, col_2):
from PIL import ImageOps
# IM = self.removeTransparancy(IM, (255,255,255))
IM = IM.convert("L")
if type(col_1) == str:
col_1 = self.RGBToHTMLColor(col_1)
col_2 = self.RGBToHTMLColor(col_2)
try:
IM = ImageOps.colorize(IM, col_1, col_2)
except:
pass
return IM
def make_full_width_empty_image(self, height=100, colour='#b40000', scale=1, width_adjust=0):
adjusted_width = self.available_width_full - width_adjust
size = (adjusted_width * scale, height * scale)
im = Image.new("RGB", size, colour)
draw = ImageDraw.Draw(im)
return im, draw, adjusted_width
def add_continue_triangles(self, draw, width, height, shift_up=4, shift_left=5, style=('multiple')):
arrow_top = 8 + shift_up
arrow_middle = 5 + shift_up
arrow_bottom = 2 + shift_up
beg_1 = 20 + shift_left
mid_1 = 16 + shift_left
beg_2 = 13 + shift_left
mid_2 = 9 + shift_left
beg_3 = 7 + shift_left
mid_3 = 3 + shift_left
if 'multiple' in style:
colour = (150, 190, 230)
colour = self.gui_timage_colour
begin = (width - beg_1, height - arrow_top)
middle = (width - mid_1, height - arrow_middle)
end = (width - beg_1, height - arrow_bottom)
draw.polygon((begin, middle, end), colour)
colour = self.adjust_colour(colour, luminosity=0.7)
begin = (width - beg_2, height - arrow_top)
middle = (width - mid_2, height - arrow_middle)
end = (width - beg_2, height - arrow_bottom)
draw.polygon((begin, middle, end), colour)
colour = self.adjust_colour(colour, luminosity=0.7)
begin = (width - beg_3, height - arrow_top)
middle = (width - mid_3, height - arrow_middle)
end = (width - beg_3, height - arrow_bottom)
draw.polygon((begin, middle, end), colour)
elif 'single' in style:
beg_3 = 10 + shift_left
mid_3 = 4 + shift_left
direction = style[1]
colour = style[2]
if "(" in colour:
colour = eval(colour)
arrow_width = 12
if direction == "right":
begin = (width - beg_3, height - arrow_top)
middle = (width - mid_3, height - arrow_middle)
end = (width - beg_3, height - arrow_bottom)
elif direction == "up":
begin = (width - beg_3 + arrow_width / 2, height - arrow_top)
middle = (width - mid_3, height - arrow_bottom)
end = (width - beg_3, height - arrow_bottom)
elif direction == "down":
begin = (width - beg_3, height - arrow_top)
middle = (width - mid_3, height - arrow_top)
end = (width - beg_3 + arrow_width / 2, height - arrow_bottom)
elif direction == "left":
begin = (width - beg_3 + arrow_width, height - arrow_top)
middle = (width - beg_3, height - arrow_middle)
end = (width - beg_3 + arrow_width, height - arrow_bottom)
if begin:
draw.polygon((begin, middle, end), colour)
def adjust_colour(self, colour, hue=0, luminosity=1, saturation=1):
'''
Adjusts the colour of a color value. It can be either a pre-defined value
like "highlight" or a rgb value. Hue, luminosity and saturation can be
controlled by the optional parameters.
Returns a modified rgb color value.
:type colour: string
:return nc: string
'''
hue = float(hue)
if not luminosity:
luminosity = 1
try:
luminosity = float(luminosity)
saturation = float(saturation)
except:
luminosity = 1
saturation = 1
if colour == 'base':
colour = self.params.timage.base_colour.rgb
if colour == "bg":
colour = self.params.html.bg_colour.rgb
if colour == "highlight":
colour = self.params.html.highlight_colour.rgb
if colour == "gui_html_table_bg_colour":
colour = self.params.html.table_bg_colour.rgb
else:
try:
colour = colour.rgb
except:
colour = colour
if "#" in str(colour):
colour = ImageColor.getrgb(colour)
try:
c = self.colorsys.rgb_to_hls(*[x / 255.0 for x in colour])
except:
pass
l = list(c)
l[0] = l[0] + hue / 360.
if l[0] > 1:
l[0] = l[0] - 1
l[1] = l[1] * luminosity
l[2] = l[2] * saturation
c = tuple(l)
nc = self.colorsys.hls_to_rgb(*[x for x in c])
l = []
for item in nc:
value = int(item * 255)
if value >= 255:
value = 255
if value <= 0:
value = 0
l.append(value)
nc = tuple(l)
return nc
def gradient_bgr(self, draw, width, height, colour=(237, 237, 235), fraction=0.85, increment=10, step=1):
inc = increment
if "#" in colour: colour = self.HTMLColorToRGB(colour)
for i in xrange(int(height * fraction)):
if i < height / inc:
adjusted_step = 0.6 * step
elif height / inc < i < (height / inc) * 2:
adjusted_step = 1.2 * step
else:
adjusted_step = 1.4 * step
incrementA = int(adjusted_step * i * (58 / height))
incrementB = int(adjusted_step * i * (44 / height))
begin = (0, i)
end = (width, i)
R = int(colour[0] - incrementA)
G = int(colour[1] - incrementA)
B = int(colour[2] - incrementB)
# print i, R,G,B
draw.line((begin , end), fill=(R, G, B))
def sort_out_encoding():
font = ImageFont.truetype("%s" % font_file, font_size, encoding=self.test_encoding("unic")) # #Leave in for Debug!
try:
font_file = self.fonts.get(font_name, "arialuni.ttf")
font = ImageFont.truetype("%s" % font_file, font_size, encoding=self.test_encoding("unic"))
except:
print "The font %s is required for this option." % font_name
self.abort = True
pass
def textsize(self,
draw,
txt,
font_size,
font_name='Vera',
titleCase=False,
lowerCase=False,
translate=True):
return self.write_text_to_draw(draw=draw, txt=txt, font_name=font_name, font_size=font_size, titleCase=titleCase, lowerCase=lowerCase, translate=translate, getXY_only=True)
def get_im_data_d_from_filename(self, filename, units='pt', target_width=0, max_height=0):
import base64
if type(filename) == unicode or type(filename) == str:
if os.path.exists(filename):
im = Image.open(filename)
data = open(filename, 'rb').read()
data = base64.b16encode(data)
d = {}
if units == 'twip':
multiplier = 10
else:
multiplier = 1
if not target_width:
d.setdefault('image_height', im.size[1] * multiplier)
d.setdefault('image_width', im.size[0] * multiplier)
else:
h = int((im.size[1] / im.size[0]) * target_width)
if max_height and h > max_height:
h = max_height
w = int((im.size[0] / im.size[1]) * max_height)
else:
w = target_width
d.setdefault('image_height', h)
d.setdefault('image_width', w)
d.setdefault('image_format', im.format)
d.setdefault('image_data', data)
return d
def get_im_and_draw_from_filename(self, filename):
if type(filename) == unicode:
if os.path.exists(filename):
im = Image.open(filename)
draw = ImageDraw.Draw(im)
else:
im = None
draw = None
return im, draw
def make_round_corners(self, im, radius=10, colour=(80, 130, 130)):
cache = {}
im = RoundedCorners.round_image(im, cache, radius, solid_colour=colour)
return im
def deal_with_encodings_and_languages(self):
''' Determines the font and some font settings for various encodings '''
encoding = 'unic'
original_font_size = self.font_size
if self.gui_language_encoding not in self.good_encodings:
self.gui_language_encoding = "unic"
encoding = 'unic'
if self.gui_current_language == "Chinese":
self.font_name = OV.GetParam('gui.chinese_font_name')
else:
self.font_name = 'Arial UTF'
if not self.translate:
self.font_name = 'Vera'
self.font_size = original_font_size
try:
self.txt.encode('ascii')
except:
if self.gui_current_language != "Chinese":
self.font_name = 'Arial UTF'
# self.top -= 3
else:
pass
if self.gui_current_language == "Chinese":
self.font_peculiarities.setdefault("Arial UTF", {"top_adjust":-0.7,
"rel_adjust":+0.4})
elif self.gui_current_language == "Greek":
self.font_peculiarities.setdefault("Arial UTF", {"top_adjust":-1,
"rel_adjust":+0.4})
elif self.gui_current_language == "Russian":
self.font_peculiarities.setdefault("Arial UTF", {"top_adjust":-1,
"rel_adjust":+0.4})
def get_font_peculiarities(self):
self.font_peculiarities = {
"Paddington":{"top_adjust":0,
"rel_adjust":0},
"Verdana":{"top_adjust":-0.1,
"rel_adjust":+0.1},
"Trebuchet":{"top_adjust":-0.5,
"rel_adjust":+0.2},
"Helvetica":{"top_adjust":-0.5,
"rel_adjust":0.1},
"Courier":{"top_adjust":-0.1,
"rel_adjust":+0.1},
"Vera":{"top_adjust":0,
"rel_adjust":-0.1},
"Simhei TTF":{"top_adjust":-0.2,
"rel_adjust":+0.3},
}
def get_text_modifications(self):
if self.translate:
self.txt = OV.Translate("%%%s%%" % self.txt.strip()) # #Language
if self.titleCase:
self.txt = self.txt.title()
if self.lowerCase:
self.txt = self.txt.lower()
def get_valign_font_modifications(self):
if not self.valign:
return
try:
letting_width, lettering_height = self.draw.textsize(self.txt, font=self.font)
rel_size = self.valign[1]
position = self.valign[0]
self.font_size = int(rel_size * self.image_size[1])
while True:
if lettering_height < (self.image_size[1] * (rel_size + self.rel_adjust)):
self.font_size += 1
lettering_height += 1
self.txt_top += self.top_adjust
else:
break
except Exception, err:
print err
def _shorten_text(self, txt, draw, left_start, width, font):
tw = (draw.textsize(txt, font)[0])
if tw < width:
return txt
n = int(len(txt)/2)
txtbeg = txt[:n]
txtend = txt [-n:]
if left_start > width:
left_start = 50 * self.scale
else:
left_start = left_start
xx = 0
while tw > width - left_start - 5 * self.scale:
txtbeg = txt[:n]
txtend = txt [-n:]
tw = (draw.textsize("%s...%s" %(txtbeg, txtend), font)[0])
n -= 1
xx += 1
if xx > 100 * self.scale:
break
return "%s...%s" %(txtbeg, txtend)
def write_text_to_draw(self,
draw,
txt,
top_left=(1, 0),
font_name='Vera',
font_size=11,
font_colour="#000000",
align="left",
max_width=1000,
image_size=None,
titleCase=False,
lowerCase=False,
valign=None,
translate=True,
getXY_only=False,
scale=1):
# if max_width < 100:
# max_width = OV.GetParam('gui.htmlpanelwidth')
if not self.scale:
self.scale = scale
self.font_size = font_size
self.font_name = font_name
self.translate = translate
self.txt = txt
self.txt_top = top_left[1]
self.txt_left = top_left[0]
self.titleCase = titleCase
self.lowerCase = lowerCase
self.valign = valign
self.draw = draw
self.image_size = image_size
self.get_text_modifications()
self.deal_with_encodings_and_languages()
txt = self.txt
font = self.get_font(font_name=self.font_name, font_size=self.font_size)
self.font = font
txt = self._shorten_text(txt=txt, draw=draw, font=font, left_start=self.txt_left, width=max_width)
self.font_colour = font_colour
self.get_valign_font_modifications()
if align == "centre" or align == 'middle':
self.txt_left = (self.centre_text(draw, txt, font, max_width))
elif align == "right":
self.txt_left = (self.align_text(draw, txt, font, max_width, 'right'))
wX, wY = draw.textsize(txt, font=font)
if getXY_only:
return wX, wY
txt_l = []
t = ""
wXT = 0
if wX > max_width and " " in txt:
txt_in = txt.split()
for word in txt_in:
wX, wY = draw.textsize(word, font=font)
wXT += wX
if wXT < max_width:
t += " %s" % word
else:
txt_l.append(t.strip())
wXT = 0
t = "%s" % word
txt_l.append(t.strip())
else:
w_counter = 0
while wX > max_width and w_counter < 100:
w_counter += 1
txt = txt.rstrip('...')
txt = txt[:-1] + "..."
wX, wY = draw.textsize(txt, font=font)
if "
" in txt:
self.txt = txt
self.print_html_to_draw()
return
elif '
' in txt:
txt = txt.split('
')
txt_l = txt
else:
txt_l.append(txt)
if not self.abort:
if type(font_colour) != str and type(font_colour) != tuple and type(font_colour) != unicode:
try:
font_colour = font_colour.hexadecimal
except Exception, ex:
print("font_colour is ill defined: %s" % ex)
try:
i = 0
for txt in txt_l:
left = self.txt_left
top_n = self.txt_top + wY * i
fc = font_colour
f = font
if '' in txt:
t = txt.split('')
_ = t[1].split('')
t[1] = _[0]
t.append(_[1])
j = 0
for item in t:
top = int(top_n)
f = font
if j == 1:
f = self.get_font(font_name, int(font_size * 0.7))
top += int(font_size / 2)
j += 1
wX, wY = draw.textsize(item, font=f)
draw.text((left, top), item, font=f, fill=font_colour)
left += wX
else:
draw.text((left, int(top_n)), txt, font=font, fill=font_colour)
i += 1
except Exception, ex:
print "Text %s could not be drawn: %s" % (txt, ex)
else:
pass
return wX, wY
def print_html_to_draw(self):
top = self.txt_top
left = self.txt_left
gap = 5 * self.scale
self.txt = self.txt.strip().replace('\n', '')
l = self.txt.split('')
for line in l:
if not line:
continue
line = line.strip()
_ = line.split('>')
if 'class' in line:
self.css_class = _[0].strip(' ').split('class=')[1]
self.set_css_settings()
txt = ">".join(_[1:])
if '' in txt:
l = left
t = txt.split('')
for item in t:
if "" in item:
f = self.get_font("%s Bold" % self.font_name, self.font_size)
item = item.strip("")
else:
f = self.font
bX, bY = self.draw.textsize(item, font=f)
self.draw.text((l, top), item, font=f, fill=self.font_colour)
l += bX
top += self.line_height
else:
wX, wY = self.draw.textsize(txt, font=self.font)
self.draw.text((left, top), txt, font=self.font, fill=self.font_colour)
top += self.line_height
def set_css_settings(self):
c = OV.GetParam('gui.css.%s' % self.css_class)
if not c:
return
self.font_name = OV.GetParam('gui.css.%s.font_name' % self.css_class)
self.font_size = OV.GetParam('gui.css.%s.font_size' % self.css_class) * self.scale
self.font_colour = OV.GetParam('gui.css.%s.color' % self.css_class).hexadecimal
self.get_font()
self.line_height = OV.GetParam('gui.css.%s.line_height' % self.css_class) * self.scale
def addTransparancy(self, im, target_colour=(255, 255, 255)):
mask = im.point(lambda i : i == 0 and 0) # create RGB mask
mask = mask.convert('L') # mask to grayscale
mask = mask.point(lambda i : i == 0 and 0) # mask to B&W grayscale
mask = ImageChops.invert(mask)
# merge mask with image
R, G, B = im.split()
n_img = Image.merge('RGBA', (R, G, B, mask))
return n_img
def removeTransparancy(self, im, target_colour=(255, 255, 255)):
# Remove transparency
white = Image.new("RGB", im.size, target_colour) # Create new white image
r, g, b, a = im.split()
im = Image.composite(im, white, a) # Create a composite
return im
def getTxtWidthAndHeight(self, txt, font_name='Vera', font_size=12):
global sizedraw_dummy_draw
font = self.fonts[font_name]["fontInstance"].get(font_size, None)
if not font:
font = self.registerFontInstance(font_name, font_size)
wX, wY = sizedraw_dummy_draw.textsize(txt, font=font)
return wX, wY
def get_font(self, font_name=None, font_size=None):
if not font_name: font_name = self.font_name
if not font_size: font_size = self.font_size
try:
font = self.fonts[font_name]["fontInstance"].get(font_size, None)
if not font:
font = self.registerFontInstance(font_name, font_size)
self.top_adjust = 0
self.rel_adjust = 0
if self.font_peculiarities.get(font_name):
self.top_adjust = self.font_peculiarities[self.font_name].get('top_adjust', 0)
self.rel_adjust = self.font_peculiarities[self.font_name].get('rel_adjust', 0)
except:
pass
self.font = font
return font
def make_pop_image(self, d):
size = d.get('size')
bgcolour = d.get('bgcolour')
txt_l = d.get('txt')
name = d.get('name')
im = Image.new("RGB", size, bgcolour)
draw = ImageDraw.Draw(im)
margin = 4
line_count = 0
curr_pos_x = margin
curr_pos_y = margin
for t in txt_l:
txt = t.get('txt')
colour = t.get('colour')
font_size = t.get('size')
font_weight = t.get('weight')
font_name = "%s %s" % (self.gui_timage_font_name, font_weight)
font_name = font_name.strip()
after = t.get('after')
font = self.fonts[font_name]["fontInstance"].get(font_size, None)
if not font:
font = self.registerFontInstance(font_name, font_size)
wX, wY = draw.textsize(txt, font=font)
self.write_text_to_draw(
draw,
txt,
top_left=(curr_pos_x, curr_pos_y),
font_name=font_name,
font_size=font_size,
font_colour=colour,)
if '
' in after:
s = after.split('
')
if len(s) > 1:
mul = s[1]
if not mul: mul = 0
mul = int(wY * float(mul))
curr_pos_y += (wY + mul)
line_count += 1
curr_pos_x = margin
else:
curr_pos_x += wX
OlexVFS.save_image_to_olex(im, name, 2)
def draw_advertise_new(self, draw, image):
max_width = image.size[0]
max_height = image.size[1]
font_name = "%s Bold" % OV.GetParam('gui.html.font_name')
font_size = int(max_height) - 5
colour = OV.GetParam('gui.html.highlight_colour')
txt = "New!"
dX, dY = self.getTxtWidthAndHeight(txt, font_name, font_size)
from_right = 15
left_start = max_width - dX - from_right
draw.rectangle((left_start, 2, max_width - from_right, int(dY * 0.75)), fill='#ffee00')
# draw.ellipse((left_start, -dY, max_width - from_right, int(dY*0.8)), fill='#ffee00')
self.write_text_to_draw(
draw,
txt=txt,
top_left=(left_start, -1),
# align='right',
max_width=max_width - 1,
font_name=font_name,
font_size=font_size,
titleCase=True,
font_colour=colour,)
# font_size = 8
# txt = "New!"
# dX, dY = self.getTxtWidthAndHeight(txt, font_name, font_size)
# IM = Image.new('RGBA', (dX, dY))
# IMdraw = ImageDraw.Draw(IM)
# IMdraw.rectangle((0, 0, dX + 2, dY), fill='#ffee00')
# self.write_text_to_draw(
# IMdraw,
# txt = txt,
# top_left=(0, -1),
# max_width=max_width,
# font_name=font_name,
# font_size=font_size,
# titleCase=True,
# font_colour=colour,)
# OlexVFS.save_image_to_olex(IM, "new", 2)
def create_arrows(self, image, draw, height, direction, colour, type='simple', h_space=4, v_space=4, offset_y=0, char_pos=(0, 0), char_char="+", width=10, align='left', scale=1.0):
if align == 'right':
adval_parameter = OV.GetParam('gui.timage.adval')
adval = int(round(adval_parameter * scale, 0))
char_pos = (width - adval, char_pos[1])
h_space = width - h_space - adval
# h_space = width - height
arrow_height = height - (2 * v_space)
arrow_width = arrow_height
arrow_height = int(round(arrow_height * scale, 0))
arrow_width = int(round(arrow_width * scale, 0))
# h_space = int(round(h_space*scale/1,0))
v_space = int(round(v_space * (1 / scale), 0))
if arrow_width % 2 != 0:
arrow_width -= 1
arrow_height -= 1
arrow_half = int(round(arrow_width / 2, 0))
if type == 'simple':
if direction == 'up':
h_space -= 2
v_space += 2
begin = (h_space, height - v_space + 1)
middle = (h_space + arrow_half, v_space - 1)
end = (h_space + arrow_width, height - v_space + 1)
elif direction == 'down':
h_space -= 1
v_space += 1
begin = (h_space, v_space)
middle = (h_space + arrow_half, height - v_space)
end = (h_space + arrow_width, v_space)
elif direction == "right":
h_space += 1
begin = (h_space, v_space)
middle = (arrow_width + 1, height / 2)
end = (h_space, height - v_space)
elif direction == "right_":
begin = (3, 3)
middle = (9, height / 2)
end = (3, height - 3)
draw.polygon((begin, middle, end), colour)
elif type == "composite":
if direction == "up":
begin = (8, 5)
middle = (4, height - 5)
end = (8, height - 7)
draw.polygon((begin, middle, end), self.adjust_colour(colour, luminosity=0.8))
middle = (12, height - 5)
draw.polygon((begin, middle, end), self.adjust_colour(colour, luminosity=0.6))
if direction == "down":
begin = (8, height - 5)
middle = (4, 5)
end = (8, 7)
draw.polygon((begin, middle, end), fill=self.adjust_colour(colour, luminosity=0.8))
middle = (12, 5)
draw.polygon((begin, middle, end), fill=self.adjust_colour(colour, luminosity=0.6))
elif type == "char":
font_size = int(13 * scale)
font_name = "%s Bold" % self.gui_timage_font_name
if char_pos == "Auto":
wX, wY = self.getTxtWidthAndHeight(char_char, font_name, font_size)
char_pos = (width * scale - wX - 5, 1)
self.write_text_to_draw(
draw,
char_char,
top_left=char_pos,
font_name=font_name,
font_size=font_size,
titleCase=True,
font_colour=colour,)
elif type == "circle":
xy = (4, 4, 8, 8)
draw.ellipse(xy, fill=colour)
elif type == "dots":
dot_size = OV.GetParam('gui.timage.cbtn.dot_size')
pad = OV.GetParam('gui.timage.cbtn.dot_pad')
left_start = OV.GetParam('gui.timage.cbtn.dot_left')
colour_off = OV.GetParam('gui.timage.cbtn.dot_colour_off').hexadecimal
colour_on = OV.GetParam('gui.timage.cbtn.dot_colour_on').hexadecimal
l = (width - height + left_start) * scale
t = pad
b = height - pad
r = width - pad
mark = self.get_PIL_image_from_olex_VFS('%s_raw.png' % direction)
if mark:
watermark = True
if watermark:
_ = image.size[1] - (pad*scale*2)
mark = mark.resize((_,_), Image.ANTIALIAS)
image = self.watermark(image, mark, (int(round(l)), int(round(t))), opacity=1)
else:
mark_colouriszed = self.colourize(mark, (0, 0, 0), self.params.html.base_colour.rgb)
IM = Image.new('RGBA', mark.size)
IM.paste(mark_colouriszed, (0, 0), mark)
IM = self.resize_image(IM, (image.size[1], image.size[1]), name="mark_colourised")
image.paste(IM, (l, t))
return image
else:
if direction == "up":
fill = colour_on
i = 0
top = b - pad
w_counter = 0
while top > (pad + dot_size) and w_counter < 1000:
w_counter += 1
left = l + i * dot_size / 2
top = b - i * dot_size - dot_size
xy = (int(left), int(top), left + dot_size, top + dot_size)
draw.ellipse(xy, fill=fill)
i += 1
j = i
w_counter = 0
while top < (height - pad - dot_size) and w_counter < 1000:
w_counter += 1
left = l + j * dot_size / 2
top = b - i * dot_size - dot_size
xy = (int(left), int(top), left + dot_size, top + dot_size)
draw.ellipse(xy, fill=fill)
i -= 1
j += 1
elif direction == 'down':
fill = colour_off
i = 0
top = t
w_counter = 0
while (top < height - pad - dot_size * 2) and w_counter < 1000:
w_counter += 1
left = l + i * dot_size / 2
top = t + i * dot_size
xy = (int(left), int(top), left + dot_size, top + dot_size)
draw.ellipse(xy, fill=fill)
i += 1
j = i
w_counter = 0
while top > pad and w_counter < 1000:
w_counter += 1
left = l + j * dot_size / 2
top = t + i * dot_size
xy = (int(left), int(top), left + dot_size, top + dot_size)
draw.ellipse(xy, fill=fill)
i -= 1
j += 1
elif direction == "right":
im_data = OlexVFS.read_from_olex('toolbar-dot-arrow-right.png')
elif direction == "left":
im_data = OlexVFS.read_from_olex('toolbar-dot-arrow-left.png')
# IM = Image.open(StringIO(im_data))
# IM = IM.resize((height, height))
# box = (width - height, 0)
# image.paste(IM, box)
def make_simple_text_to_image(self, width, height, txt, font_name='Vera', font_size=16, bg_colour='#fff6bf', font_colour='#222222'):
IM = Image.new('RGB', (width, height), bg_colour)
draw = ImageDraw.Draw(IM)
txt = txt.strip()
self.write_text_to_draw(
draw,
top_left=(3, 3),
max_width=width - 40,
txt=txt,
font_name=font_name,
font_size=font_size,
titleCase=False,
font_colour=font_colour,)
return IM
def make_border(self, rad,
draw,
width,
height,
border_colour,
bg_colour="white",
cTopLeft=True,
cTopRight=True,
cBottomLeft=True,
cBottomRight=True,
shift=1,
border_hls=(0, 1, 1),
):
hrad = int(rad / 2 - 1)
hrad_TL = 0
hrad_TR = 0
hrad_BL = 0
hrad_BR = 0
# border_colour = bg_colour
border_colour = self.adjust_colour(border_colour, hue=border_hls[0], luminosity=border_hls[1], saturation=border_hls[2])
# border top
begin = (0, 0)
end = (width, 0)
# draw.line((begin ,end), fill=border_colour['top'])
draw.line((begin , end), fill=border_colour)
# border bottom
begin = (0, height - 1)
end = (width - 1, height - 1)
# draw.line((begin ,end), fill=border_colour['bottom'])
draw.line((begin , end), fill=border_colour)
# border left
begin = (0, 0)
end = (0, height - 1)
# draw.line((begin ,end), fill=border_colour['left'])
draw.line((begin , end), fill=border_colour)
# border right
begin = (width - 1 , 0)
end = (width - 1, 0)
# draw.line((begin ,end), fill=border_colour['right'])
draw.line((begin , end), fill=border_colour)
rect_colour = OV.GetParam('gui.html.bg_colour')
pie_colour = bg_colour
pie_colour = (0, 0, 0, 255)
rect_colour = (0, 0, 0, 255)
# top-left corner
if cTopLeft:
draw.rectangle((0, 0, hrad, hrad), fill=rect_colour)
draw.pieslice((0, 0, rad, rad), 180, 270, fill=pie_colour)
draw.arc((0, 0, rad, rad), 180, 270, fill=border_colour)
hrad_TL = hrad
# bottom-right corner
if cBottomRight:
draw.rectangle((width - hrad, height - hrad, width, height), fill=rect_colour)
draw.pieslice((width - rad - shift, height - rad - shift, width - shift, height - shift), 0, 90, fill=pie_colour)
draw.arc((width - rad - shift, height - rad - shift, width - shift, height - shift), 0, 90, fill=border_colour)
hrad_BR = hrad
# bottom-left corner
if cBottomLeft:
draw.rectangle((0, height - hrad, hrad, height), fill=rect_colour)
draw.pieslice((0, height - rad - shift, rad, height - shift), 90, 180, fill=pie_colour)
draw.arc((0, height - rad - shift, rad, height - shift), 90, 180, fill=border_colour)
hrad_BL = hrad
# top-right corner
if cTopRight:
# draw.rectangle((width-hrad, 0, width, hrad), fill=rect_colour)
# draw.pieslice((width-rad-shift, 0, width-shift, rad), 270, 360, fill=pie_colour)
draw.arc((width - rad - shift, 0, width - shift, rad), 270, 360, fill=border_colour)
hrad_TR = hrad
# border top
begin = (hrad_TL, 0)
end = (width - hrad_TR, 0)
draw.line((begin , end), fill=border_colour)
# border bottom
begin = (hrad_BL - 1, height - 1)
end = (width - hrad_BR - 1, height - 1)
draw.line((begin , end), fill=border_colour)
# border left
begin = (0, hrad_TL)
end = (0, height - hrad_BL - 1)
draw.line((begin , end), fill=border_colour)
# border right
begin = (width - 1 , hrad_TR)
end = (width - 1, height - hrad_TL)
draw.line((begin , end), fill=border_colour)
def make_pie_graph(self, number=3, segments=[('R', 0.5, '#ee0000'), ('G', 0.5, '#00ee00')], rotation=-90, name='fred'):
rotation = int(rotation)
number = int(number)
red = self.gui_red
green = self.gui_green
blue = self.gui_blue
grey = self.gui_grey
colours = [red, green, blue, grey]
map_l = []
if not number:
number = len(segments)
if number == 2:
rotation = 90
segments = [('Solve', 0.5, red), ('Refine', 0.5, green)]
rad_factor = 4
if number == 3:
segments = [('R', 0.333, red), ('G', 0.333, green), ('B', 0.333, blue)]
rad_factor = 4
if number == 4:
rotation = -135
segments = [('R', 0.25, red), ('G', 0.25, green), ('B', 0.25, blue), ('Grey', 0.25, '#888888')]
rad_factor = 3.4
colour = (0, 0, 0, 0)
colour = OV.GetParam('gui.html.bg_colour').rgb
size = (300, 300)
im_size = (size[0] + 1, size[1] + 1)
IM = Image.new('RGBA', im_size, colour)
draw = ImageDraw.Draw(IM)
font_size = int(size[0] / 8)
font_name = 'Vera Bold'
font = self.get_font(font_size=font_size, font_name=font_name)
font_colour = '#ababab'
border_colour = "#ffffff"
border_width = 0
rad_width = size[0] - 2 - border_width * 2
rad_height = size[1] - 2 - border_width * 2
margin = 0
center = (int(size[0] / 2), int(size[1] / 2))
draw.ellipse((margin, margin, rad_width, rad_height), fill=border_colour)
curr_end = rotation
i = 0
for segment in segments:
var = segment[0]
map_l.append({'var':var, 'href':var, 'target':var})
value = 1 / len(segments)
pie_colour = colours[i]
begin = int(curr_end)
end = begin + int(round(360 * value, 0))
draw.pieslice((margin + border_width, margin + border_width, rad_width, rad_height), begin, end, fill=pie_colour)
curr_end = end
i += 1
curr_end = 0
if number == 2:
curr_end = 180
elif number == 4:
curr_end = -45
i = 0
for segment in segments:
var = segment[0]
pie_colour = colours[i]
font_colour = self.adjust_colour(pie_colour, luminosity=1.6)
font_colour = '#ffffff'
begin = int(curr_end)
end = begin + int(round(360 * value, 0))
angle = (end - begin) / 2 + begin
angle = math.radians(angle)
wX, wY = self.textsize(draw, var, font_size, font_name)
left = (center[0] + math.sin(angle) * rad_width / rad_factor) - wX / 2
top = ((center[1] + (math.cos(angle) * -1) * rad_height / 3.2)) - wY / 2
draw.text((int(left), int(top)), var, font=font, fill=font_colour)
curr_end = end
i += 1
map_width = 200
map_height = 100
pie_map = self.make_pie_map(map_l, (map_width, map_height))
html = '''
''' % (pie_map)
IM.save("%s/%s.png" % (OV.DataDir(), name))
OlexVFS.save_image_to_olex(IM, name, 1)
OlexVFS.write_to_olex('pie.htm', html, True)
OV.UpdateHtml()
def get_PIL_image_from_olex_VFS(self, name):
from StringIO import StringIO
if olx.fs.Exists(name) != "true":
from PilTools import timage
a = timage()
a.make_images_from_fb_png()
if olx.fs.Exists(name) == "true":
_ = OlexVFS.read_from_olex(name)
sio = StringIO(_)
retVal = Image.open(sio)
else:
retVal = False
return retVal
def trim_image(self, im, trimcolour=None, padding=2, border=0.5, border_col='#aaaaaa', dry=False, target_size=None):
''' Takes either an image or a path to an image, then trims off all whitespace and either returns the trimmed image or saves it to the same path as the original one '''
from PIL import Image, ImageChops, ImageOps
p = None
if type(im) == str or type(im) == unicode:
im = im.strip("'")
im = im.strip('"')
if os.path.exists("%s" % im):
p = im
try:
im = Image.open("%s" % im)
except:
print("Sorry, cannot trim image of this kind")
return
else:
print("No such image")
return
if not trimcolour:
import struct
trimcolour = "#%s" %self.dec2hex(int(olx.gl.lm.ClearColor()))
_ = struct.unpack("4B",struct.pack(">I",int(olx.gl.lm.ClearColor())))
trimcolour = (_[3], _[2], _[1])
original_width = im.size[0]
bg = Image.new(im.mode, im.size, trimcolour)
diff = ImageChops.difference(im, bg)
bbox = diff.getbbox()
im = im.crop(bbox)
padding = int(im.size[0] / 100 * padding)
border = int(im.size[0] / 100 * border)
border_col = str(border_col)
adjust = 0
if target_size:
curr_width = im.size[0] + padding * 2 + border * 2
diff = target_size - curr_width
padding += int(diff / 2)
curr_width = im.size[0] + padding * 2 + border * 2
if curr_width > target_size:
adjust = -1
elif curr_width < target_size:
padding += 1
adjust = -1
if padding:
im = ImageOps.expand(im, border=padding, fill=trimcolour)
if adjust:
bbox = (0, 0, im.size[0] - 1, im.size[1])
im = im.crop(bbox)
if border:
im = ImageOps.expand(im, border=border, fill=border_col)
if dry:
return im.size[0], original_width
if p:
im.save(p)
else:
return im
def make_pie_map(self, map_l, size):
width = size[0]
height = size[1]
map = "'''
# elif len(map_l) == 3:
# map = '''
# "
return map
IT = ImageTools()
IT.get_available_width()
if olx.HasGUI() == 'true':
OV.registerMacro(IT.resize_to_panelwidth, 'i-Image&;c-Colourize')
OV.registerFunction(IT.make_pie_graph, False, 'it')
OV.registerFunction(IT.trim_image, False, 'it')