def animate_slice(sliceviewer, name, start, end, filename, num_frames=10, font_size=24): """Generate an animated gif of a 2D slice moving through a third dimension. Args: sliceviewer (SliceViewer): A sliceviewer instance. name (str): The name of the third dimension to use. start (float): The starting value of the third dimension. end (float): The end value of the third dimension. filename (str): The file to save the gif to. Kwargs: num_frames (int): The number of frames the gif should contain. font_size: (int): The size of the caption. Example: ws = CreateMDWorkspace(3, Extents=[-10,10,-10,10,-10,10], Names=["X","Y","Z"], Units=["u","u","u"]) FakeMDEventData(ws, PeakParams=[10000,0,0,0,1]) sv = plotSlice(ws) #Resize and configure the slice viewer how you want the output to look sv.setNormalization(1) # We need to normalize by volume in this case, or the data won't show up #This will create a gif iterating from Z = -1 to Z = 1 animate_slice(sv, "Z", -1, 1, "output.gif") """ #Generate all the individual frames images = [] for slice_point in numpy.linspace(start, end, num_frames): sliceviewer.setSlicePoint(name, slice_point) sliceviewer.refreshRebin() qimg = sliceviewer.getImage().toImage() data = QByteArray() buf = QBuffer(data) qimg.save(buf, "PNG") image = Image(blob=str(data)) captionstrip_size = font_size + 10 #To add whitespace to the top, we add a vertical border, #then crop out the bottom border image.border(Color("#fff"), 0, captionstrip_size) image.crop(0, 0, image.width, image.height - captionstrip_size) #Write the caption into the whitespace draw = Drawing() draw.font_size = font_size draw.text(5, font_size, "%s = %g" % (name, slice_point)) draw(image) images.append(image) #Create a new image with the right dimensions animation = Image(width=images[0].width, height=images[0].height) #Copy in the frames from all the generated images for image in images: animation.sequence.append(image.sequence[0]) #Drop the initial blank frame del animation.sequence[0] #Write the animation to disk animation.save(filename=filename)
def animate_slice(sliceviewer, name, start, end, filename, num_frames=10, font_size=24): """Generate an animated gif of a 2D slice moving through a third dimension. Args: sliceviewer (SliceViewer): A sliceviewer instance. name (str): The name of the third dimension to use. start (float): The starting value of the third dimension. end (float): The end value of the third dimension. filename (str): The file to save the gif to. Kwargs: num_frames (int): The number of frames the gif should contain. font_size: (int): The size of the caption. Example: ws = CreateMDWorkspace(3, Extents=[-10,10,-10,10,-10,10], Names=["X","Y","Z"], Units=["u","u","u"]) FakeMDEventData(ws, PeakParams=[10000,0,0,0,1]) sv = plotSlice(ws) #Resize and configure the slice viewer how you want the output to look sv.setNormalization(1) # We need to normalize by volume in this case, or the data won't show up #This will create a gif iterating from Z = -1 to Z = 1 animate_slice(sv, "Z", -1, 1, "output.gif") """ #Generate all the individual frames images = [] for slice_point in numpy.linspace(start, end, num_frames): sliceviewer.setSlicePoint(name, slice_point) sliceviewer.refreshRebin() qimg = sliceviewer.getImage().toImage() data = QByteArray() buf = QBuffer(data) qimg.save(buf, "PNG") image = Image(blob=str(data)) captionstrip_size = font_size + 10 #To add whitespace to the top, we add a vertical border, #then crop out the bottom border image.border(Color("#fff"), 0, captionstrip_size) image.crop(0, 0, image.width, image.height - captionstrip_size) #Write the caption into the whitespace draw = Drawing() draw.font_size = font_size draw.text(5, font_size,"%s = %g" % (name,slice_point)) draw(image) images.append(image) #Create a new image with the right dimensions animation = Image(width=images[0].width, height=images[0].height) #Copy in the frames from all the generated images for image in images: animation.sequence.append(image.sequence[0]) #Drop the initial blank frame del animation.sequence[0] #Write the animation to disk animation.save(filename=filename)
def alt_main(self, caller, dialogue): #pick one background for the whole strip bg = randomize_background() # First line is the @paste-to start marker dialogue = dialogue[1:] title = None if dialogue[0].find('title:') > -1: title = dialogue[0].replace('title:', '') dialogue = dialogue[1:] scenes, actors = dialogue_parser(dialogue) ### DOGE # scenes and actors are both empty if scenes == OrderedDict() and actors == OrderedDict(): shibe = make_doge(dialogue) return "http://dejablabspace.com/static/doge/%s" % shibe # Assign a random avatar to each character tards = listdir( '/home/donginger/donginger/development/plugins/py_toon/characters/' ) shuffle(tards) for a in actors.values(): # These 3 lines will standardize the aliases vs real chillmin names for x in self.conf["aliases"].items(): if a.name.lower() in x[1]: a.name = x[0].capitalize() if 'r_' + a.name.lower() + '.png' in tards: a.set_avatar( tards.pop(tards.index('r_' + a.name.lower() + '.png'))) else: nt = [] for t in tards: if t[:2] != 'r_': nt.append(t) shuffle(nt) a.set_avatar(nt.pop()) a.place() # SETUP A SCENE all_panels = [] firstb = Image(width=500, height=500, background=Color('white')) draw.font = 'plugins/py_toon/fonts/BalsamiqSansBold.ttf' draw.font_size = 18 draw.text_alignment = 'left' draw.fill_color = Color('black') texty = 50 if title is None: #generate a random title from a dialogue line while True: s = choice(scenes.keys()) st = scenes[s] rline = st[0][1] words = rline.split(' ') if words != [''] and len(words) >= 1: break title_tup = words[:randrange(4, 5)] title = ' '.join(title_tup) if title[-1] in (',', ':', '-'): title = title[:-1] tmet = draw.get_font_metrics(firstb, title, True) tx = 250 - int(tmet.text_width / 2) draw.text(tx, texty, textwrap.fill(title, 40)) texty += 40 draw.font_size = 16 draw.text(30, texty, "With:") texty += 35 draw.font = 'plugins/py_toon/fonts/DejaVuSansMono.ttf' draw.font_size = 15 for peep in actors.values(): with peep.img.clone() as av: av.resize(60, 60) av.x = 10 av.y = texty firstb.composite(av, av.x, av.y) draw.text(av.width + 25, texty + 32, peep.name) texty += 65 firstb.border(Color('white'), 10, 10) draw(firstb) all_panels = [firstb] draw.clear() for scene in scenes.items(): ### Decide if we need a double-wide bottom panel last_scene_id = scenes.keys()[-1:] if scene[0] == last_scene_id[0] and scene[0] > 1 and len( scenes) % 2 == 0: panel = Panel(background=bg, chars=actors, scene=scene, doublewide=True) else: panel = Panel(background=bg, chars=actors, scene=scene) all_panels.append(panel.setup()) part = build_strip(all_panels, title) url = "http://dejablabspace.com/static/%s" % part return url
class Panel: def __init__(self, background=None, chars=None, scene=None, doublewide=False): if background is None: background = randomize_background() self.background = Image(filename=background) self.doublewide = doublewide if self.doublewide is True: self.background.crop(0, 0, self.background.height, self.background.height) self.background.transform(resize='1000x500^') self.background.transform('1000x500') else: self.background.crop(0, 0, self.background.height, self.background.height) self.background.transform(resize='500') self.background.transform(resize='500x500') self.chars = chars self.scene = scene draw.font = 'plugins/py_toon/fonts/DejaVuSansMono.ttf' draw.font_size = 15 draw.text_kerning = 1 draw.text_alignment = 'left' def setup(self): self.add_characters() self.speech_bubbles() self.background = self.render() return self.background def speech_bubbles(self): curx = 15 cury = 15 for action in self.scene[1]: actor = action[0] line = action[1] if not line: continue line = textwrap.fill(line, 20) metrics = draw.get_font_metrics(self.background, line, True) ctext = int(metrics.text_width / 2.0) draw.fill_color = Color('white') draw.stroke_color = Color('black') draw.stroke_width = 1.0 char_center = actor.img.x + int(actor.img.width / 2.0) text_center = int(metrics.text_width / 2.0) if len(self.scene[1]) == 1: cury = randrange(50, 125 + 20) else: max_y = cury + 20 if max_y < 1: max_y = 245 cury = randrange(cury, max_y) curx = char_center - text_center if curx < 25: curx = 25 if curx > self.background.width - int(metrics.text_width): curx = self.background.width - int(metrics.text_width) - 15 curx = int(curx) cury = int(cury) if line.strip() != '': draw.round_rectangle(curx - 10, cury, curx + metrics.text_width + 10, cury + metrics.text_height + 5, 5, 5) draw.fill_color = Color('black') draw.text(curx, cury + 15, line) curx += metrics.text_width + 10 cury += int(metrics.text_height + 10) def add_characters(self): parts = self.background.width / len(self.chars.keys()) curx = 0 cury = 0 char_count = 0 for i in self.chars.items(): char = i[1] if self.doublewide is True: #char.img.resize(175, 175) char.img.transform(resize='x150') else: char.img.resize(125, 125) ### contain the character in this "box" char_pos = curx + parts - char.img.width print 'char_pos:', char_pos if char_pos < 1: return 'Not enough space to fit everybody.' curx = randrange(curx, char_pos) cury = self.background.height - char.img.height char.img.x = curx char.img.y = cury char_count += 1 curx = parts * char_count if char_count == 2: char.flip() self.background.composite(char.img, char.img.x, char.img.y) draw(self.background) if char_count == 2: ### unflip char.flip() def render(self): if self.doublewide is False: self.background.border(Color('white'), 5, 5) else: self.background.border(Color('white'), 10, 10) draw(self.background) draw.clear() return self.background
def border(image: Image, colour: str, width: int, height: int) -> None: with Color(colour) as color: image.border(color=color, width=width, height=height, compose="atop")
img = Image(filename=file) changed = False # resize if img.width > max_size or img.height > max_size: if img.width > img.height: ratio = img.width / img.height img.resize(max_size, round(max_size / ratio)) else: ratio = img.height / img.width img.resize(round(max_size / ratio), max_size) changed = True # extend width = math.ceil(img.width / step_size) * step_size height = math.ceil(img.height / step_size) * step_size if img.width != width or img.height != height: bw = (width - img.width) // 2 bh = (height - img.height) // 2 img.border(color=Color('transparent'), width=bw, height=bh) changed = True # save? if changed: print('Saving: %s (%d, %d)... ' % (file, img.width, img.height)), img.save(filename=file) print('Done!') else: print('Skipping %s' % file)
# -compose screen -composite neon_sign.gif with Drawing() as draw: text = ' I M Examples ' draw.font = 'Anaconda-Regular' draw.font_size = 72 (w, h) = calcSuitableImagesize(draw, text) # make text image textimg = Image(width=w, height=h, background=Color('black')) draw.gravity = 'center' draw.fill_color = Color('dodgerblue') draw.text(0, 0, text) draw(textimg) textimg.border(Color('black'), 30, 30) # make shadow image shadowimg = textimg.clone() blur(shadowimg, 0, 25) shadowimg.level(black=0.0, gamma=1.0, white=0.5) # composite all canvas = Image(width=shadowimg.width, height=shadowimg.height) canvas.composite(shadowimg, 0, 0) canvas.composite_channel('default_channels', textimg, 'screen') canvas.save(filename='sample40.png') shadowimg.destroy() textimg.destroy() canvas.destroy()
def alt_main(self, caller, dialogue): #pick one background for the whole strip bg = randomize_background() # First line is the @paste-to start marker dialogue = dialogue[1:] title = None if dialogue[0].find('title:') > -1: title = dialogue[0].replace('title:', '') dialogue = dialogue[1:] scenes, actors = dialogue_parser(dialogue) ### DOGE # scenes and actors are both empty if scenes == OrderedDict() and actors == OrderedDict(): shibe = make_doge(dialogue) return "http://dejablabspace.com/static/doge/%s" % shibe # Assign a random avatar to each character tards = listdir('/home/donginger/donginger/development/plugins/py_toon/characters/') shuffle(tards) for a in actors.values(): # These 3 lines will standardize the aliases vs real chillmin names for x in self.conf["aliases"].items(): if a.name.lower() in x[1]: a.name = x[0].capitalize() if 'r_' + a.name.lower() + '.png' in tards: a.set_avatar(tards.pop(tards.index('r_' + a.name.lower() + '.png'))) else: nt = [] for t in tards: if t[:2] != 'r_': nt.append(t) shuffle(nt) a.set_avatar(nt.pop()) a.place() # SETUP A SCENE all_panels = [] firstb = Image(width=500, height=500, background=Color('white')) draw.font = 'plugins/py_toon/fonts/BalsamiqSansBold.ttf' draw.font_size = 18 draw.text_alignment = 'left' draw.fill_color = Color('black') texty = 50 if title is None: #generate a random title from a dialogue line while True: s = choice(scenes.keys()) st = scenes[s] rline = st[0][1] words = rline.split(' ') if words != [''] and len(words) >= 1: break title_tup = words[:randrange(4,5)] title = ' '.join(title_tup) if title[-1] in (',',':','-'): title = title[:-1] tmet = draw.get_font_metrics(firstb, title, True) tx = 250 - int(tmet.text_width / 2) draw.text(tx, texty, textwrap.fill(title, 40)) texty += 40 draw.font_size = 16 draw.text(30, texty, "With:") texty += 35 draw.font = 'plugins/py_toon/fonts/DejaVuSansMono.ttf' draw.font_size = 15 for peep in actors.values(): with peep.img.clone() as av: av.resize(60, 60) av.x = 10 av.y = texty firstb.composite(av, av.x, av.y) draw.text(av.width + 25, texty + 32, peep.name) texty += 65 firstb.border(Color('white'), 10, 10) draw(firstb) all_panels = [firstb] draw.clear() for scene in scenes.items(): ### Decide if we need a double-wide bottom panel last_scene_id = scenes.keys()[-1:] if scene[0] == last_scene_id[0] and scene[0] > 1 and len(scenes) % 2 == 0: panel = Panel(background=bg, chars=actors, scene=scene, doublewide=True) else: panel = Panel(background=bg, chars=actors, scene=scene) all_panels.append(panel.setup()) part = build_strip(all_panels, title) url = "http://dejablabspace.com/static/%s" % part return url
class Card(object): """Individual object containing an image and actions to manipulate it. Posible kwargs to __init__ are filename, file, image, blob. it will load the image from there""" def __init__(self, *args, **kwargs): """Init a new cards with *img* being a wand.image.Image object""" self.img = Image(*args, **kwargs) self.border = None self.changed = True self.pixmap() def __del__(self): self.img.destroy() def format(self, fmt=None): if fmt is None: return self.img.format.lower() else: self.img.format = fmt @set_changed def resize(self, width, height, newres=300): """Resize this card to (*width*, *height*) inches, with a resolution of *newres*""" self.img.transform(resize=str(int(width*newres)) + "x" + str(int(height*newres)) + "!") self.img.reset_coords() self.img.resolution = (newres, newres) return newres def width(self): return self.img.size[0] def height(self): return self.img.size[1] def reset_coords(self): self.img.reset_coords() @set_changed def set_border(self, border): """Set a new *border* for this card""" if self.border is not None: self.del_border() self.border = border with Color(self.border.colour) as colour: self.img.border(colour, self.border.wide, self.border.wide) @set_changed def crop(self, *args, **kwargs): """Crop this card *top*, *bottom*, *left* and *right* pixels""" w, h = self.img.size if "right" in kwargs: kwargs["right"] = w - kwargs["right"] if "bottom" in kwargs: kwargs["bottom"] = h - kwargs["bottom"] self.img.crop(*args, **kwargs) self.reset_coords() def del_border(self): """Remove the border of this card""" if self.border is not None: w = self.border.wide self.crop(top=w, bottom=w, right=w, left=w) self.border = None self.changed = True @set_changed def trim(self, fuzz=13): self.img.trim(fuzz=fuzz) self.reset_coords() def save_as(self, filename): """Save this card in a file named *filename*""" self.img.save(filename = filename) def split(self, rows, cols, separation=0): """Divide this cards in *rows* by *cols* cards, and returns a list""" width, hight = self.img.size width, hight = (int(width), int(hight)) cardWidth = (width - separation * (cols-1)) / cols cardHight = (hight - separation * (rows-1)) / rows res = [] for i in range(rows): for j in range(cols): with self.img.clone() as clon: clon.crop(top=i*cardHight+i*separation, width=cardWidth, left=j*cardWidth+j*separation, height=cardHight) clon.reset_coords() res.append(Card(image=clon)) return res @set_changed def round_corners(self): """Round the corners of the card (setting them to alpha)""" pass def clone(self): c = Card(image=self.img.clone()) c.border = self.border return c def pixmap(self): """Update and returns the pixmap (QPixmap) of the contained image""" if self.changed: self._pixmap = QPixmap(QImage.fromData(self.img.make_blob("jpg"), "jpg"))#self.img.format)) self.changed = False return self._pixmap