def iris(self, img, n): "Apply 'iris' effect" size = img.size r = self.irisRect(size, n) newImg = Image(size) Image(img.surface.subsurface(r)).blitTo(newImg, r.topleft) return newImg
def _collideDraw(self): "Draw collision shape (circle or polygon)" img = Image(pygame.display.get_surface()) s = self.shape if type(s) is Circle2D: circ = Image.ellipse(s.radius, fill=self._collideRegion[1], stroke=None) circ.blitTo(img, tuple(s.center), CENTER) else: img.plot(s.points, fill=self._collideRegion[1], stroke=None, closed=True)
def getImage(self): s = self.getState() if s == self.FOCUS: img = Image.text(self.display + " ", self.font, self.color) img = Image(self.drawCursor(img.surface)) img = self.crop((img,), self.scroll)[0].style(bgColor=self.colors[s], pad=self.pad, border=self.border, borderColor=self.borderColor) return img else: return super().getImage()
def title(self, txt, posn=6, offset=(0,0), **kwargs): """Render and position a title: -1: Left of top end of y-axis 0: Below right end of x-axis 1-4: Centred outside grid edge 5-8: Centred inside image edge """ img = Image.text(txt, **kwargs) if posn % 2: img = img.rotate(-90) if posn > 4: w, h = self.size cx, cy = self.center x = 0 if posn == 7 else w-1 if posn == 5 else cx y = 0 if posn == 6 else h-1 if posn == 8 else cy a = (EAST, NORTH, WEST, SOUTH)[posn-5] else: xmin, xmax, ymin, ymax = self.limit if posn > 0: x0, y0 = self.coords((xmin, ymin)) x1, y1 = self.coords((xmax, ymax)) cx, cy = (x0 + x1) // 2, (y0 + y1) // 2 x = x0 if posn == 3 else x1 if posn == 1 else cx y = y1 if posn == 2 else y0 if posn == 4 else cy a = (WEST, SOUTH, EAST, NORTH)[posn-1] else: xy = (xmax, 0) if posn == 0 else (0, ymax) x, y = self.coords(xy) a = NE img.blitTo(self, (x + offset[0], y + offset[1]), a)
def gridLabel(self, x, n, formats=(None,None), anchors=(NORTH, EAST), rotate=(0,-90), offsets=((0,0,0,0)), **kwargs): "Add labels to the gridlines" if formats[n]: img = Image.text(formats[n].format(x), **kwargs) if rotate[n]: img = img.rotate(rotate[n]) posn = (0, x) if n else (x, 0) posn = add(self.coords(posn), offsets[2*n:2*n+2]) img.blitTo(self, posn, anchors[n])
def makeImages(self, style=0, mark=None): sz = fontHeight(self) if style: r = sz // 2 img0 = Image.ellipse(r, fill=self.bgColor, stroke=self.color, strokeWeight=self.border) else: img0 = Image.rect((sz,sz), fill=self.bgColor, stroke=self.color, strokeWeight=self.border) img1 = img0.clone() if mark: if mark[0]: mark[0].blitTo(img0) if mark[1]: mark[1].blitTo(img1) elif style: pygame.draw.circle(img1.surface, self.color, (r,r), r//2) else: sz -= 2 pygame.draw.line(img1.surface, self.color, (1,1), (sz,sz)) pygame.draw.line(img1.surface, self.color, (1,sz), (sz,1)) return img0, img1
def apply(self, img, n): if n >= 1: return img # if self.rects is None: self.makeRects(*img.size) i = 0 n = (1 - n)**self.power w, h = img.size imgTr = Image(img.size) for r in self.rects: tile = Image(img.surface.subsurface(r)) vx, vy, s = self.tiles[i] x, y = r.center diag = sqrt(r.width**2 + r.height**2) / 2 x += vx * (diag + max(x, w - x)) * n y += vy * (diag + max(y, h - y)) * n i += 1 tile.rotate(s * n).blitTo(imgTr, (x, y), CENTER) return imgTr
def getIcon(self, item): sz = self.metric[0] if item == "..": ext = item else: ext = item.split(".")[-1].lower() if "." in item else "" item = self.cwd + "/" + item if os.path.isdir(item): ext = True for img in self.iconMap: imap = self.iconMap[img] exts = imap[1] if ext in exts: if imap[0] == None: try: icon = Image(self.imageFile(img)) except: icon = Image.text("?", font=self.font) imap[0] = icon return imap[0].fit(sz) img = self.iconMap["file"][0] if img == None: self.iconMap["file"][0] = img = Image(self.imageFile("file")).fit(sz) return img
def _makeCostumes(cls, colors=None): "Create robot costumes from the specified colours" if cls._costumes is None: cls._costumes = Image(sc8prPath("robot/robot.png")) img = cls._costumes.clone() if colors: px = PixelArray(img.surface) px.replace((255, 0, 0), colors[0]) px.replace((0, 0, 255), colors[1]) return img.tiles(2)
def costumes(self, costumes): "Convert costumes to Image instances and scale to a single size; initialize costume sequence" if type(costumes) in (str, Image, pygame.surface.Surface): costumes = costumes, costumes = [Image(c) for c in costumes] size = costumes[0].size for i in range(1, len(costumes)): if costumes[i].size != size: costumes[i] = costumes[i].scale(size) self._costumes = costumes self._costumeSeq = tuple(range(len(self.costumes)))
def __init__(self, data=None, name=None, posn=(0,0), **kwargs): "Data may be str, Surface, Image, or list/tuple of Images; if str, kwargs may specify color and altColor" super().__init__(name, posn) self.setStyle(**kwargs) if not data: data = name t = type(data) if t == str: data = self.renderText(data) elif t == pygame.Surface: data = Image(data) if type(data) not in (list, tuple): data = (data, data) self.data = data
def __init__(self, text=None, icon=None, iconRight=None, textSize=None, iconSize=None, name=None, **kwargs): super().__init__(text, name if name else text, **kwargs) metric = self.metrics() w, h = metric[2] imgs = [] if textSize != None: self.textSize = textSize if iconSize != None: self.iconSize = iconSize left, right = self.iconSize for i in self.data: img = Image((w, h)) i.blitTo(img, (h * left + self.pad, 0)) if icon: self.fitIcon(icon, metric[0]).blitTo(img) if iconRight: self.fitIcon(iconRight, metric[1]).blitTo(img, (w - h * right, 0)) imgs.append(img) self.data = imgs self.getSize()
def make(data, handler=None, posn=None, main=True): name, data = data if main: items = [] h = fontHeight(MenuItem) MenuItem.back = Image(sc8prPath("icons/menu.png")).scale((h, h)) else: items = [MenuItem(name, MenuItem.back, iconSize=(1,0)).backLink()] for i in data: isStr = type(i) == str items.append(MenuItem(i if isStr else i[0], iconSize=(0,0))) if not isStr: items[-1].link = Menu.make(i, handler, posn, False) menu = Menu(items, name, posn) if handler: menu.bind(handler) if main: pass return menu
def __init__(self, *archive, interval=None, gui=False, wait=True): self.data = [] self.interval = interval self.gui = gui if archive: if len(archive) == 1: self.load(archive[0], wait) else: archive, nums = archive if nums is True: nums = range(1, 1 + self.lastFileIndex(archive)) file = self.output if file: print("Loading and compressing images...", file=file) for i in nums: fn = archive.format(i) self.capture(Image(fn)) if file and i % 50 == 0: print(i, file=file)
def leds(self): "Draw luminous LED indicators" fc = self.frontColor colors = [self.downColor, fc if fc else (0, 0, 0), self.penColor] r1 = self.width / 5 r2 = r1 / 2.5 a = (self.angle + 60) * DEG x0, y0 = self.posn led = [] for c in colors: x = x0 + r1 * cos(a) y = y0 + r1 * sin(a) if c is not None: img = Image.ellipse(r2, c, (0, 0, 0)) xy = rectAnchor((x, y), img.size, CENTER).topleft led.append((img, xy)) a -= pi / 1.5 if c: self._penPosn = True if self.centerPen else (round(x), round(y)) return led
def _downColor(self): "Calculate downward colour-sensor value" d = self.radius // 8 r = 2 * d size = r, r r = 0.75 * self.radius posn = vsum(vec2d(r, self.angle * DEG), self.posn, (-d, -d)) sk = self.sketch self._downRect = Rect(posn + size) if sk.sprites._debugCollide: Image(size, self.downColor).blitTo(posn=posn) try: if sk.bgImage: srf = sk.scaledBgImage.surface.subsurface(posn + size) else: srf = None if sk.bgColor: img = Image(size, sk.bgColor) if srf: img.surface.blit(srf, (0, 0)) else: img = Image(srf) return noise(img.averageColor(), self.sensorNoise, alpha=255) except: return None
def fitIcon(self, icon, sz): icon = Image(icon) if sz != icon.size: icon = icon.fit(sz) return icon
def renderText(self, txt, align=CENTER): "Convert text to Image for enabled and disabled states" return Image.text(txt, self.font, self.color, align=align), Image.text(txt, self.font, self.altColor, align)
def fit(cls, *imgs, font=None): "Scale images based on font size" sz = fontHeight(font if font else cls.font) return [Image(img).scale((sz,sz)) if img else None for img in imgs]
def arrow(self, tail, tip, tailWidth=None, headLength=None, flatness=1, fill=None, stroke=None, strokeWeight=1): "Plot an arrow" pts = arrow(self.coords(tail), self.coords(tip), tailWidth, headLength, flatness).points Image.polygon(pts, True, fill, stroke, strokeWeight, self.size).blitTo(self)
def blit(self, img, posn, anchor=NW): "Blit an image to the plot" if not isinstance(img, Image): img = Image(img) img.blitTo(self, self.coords(posn), anchor)
def setText(self, txt, resize=False): self.imgs[0] = Image.text(txt, self.font, self.color) if resize: self.getSize(True)
def render(self): # Calculate metrics w, h = self.size px, hw = self.metrics if self._val <= self.min or self.min >= self.max: x = 0 elif self._val >= self.max: x = self.pixels - hw else: x = round(self.pad + (self._val - self.min) / (self.max - self.min) * px) if self.vertical: x = self.pixels - 1 - x - hw # Background img = Image(self.size, self.bgColor) pygame.draw.rect(img.surface, self.bgColor, (0,0) + self.size) # Tick marks if self.ticks and self.step != None: n = round((self.max - self.min) / self.step) tick0 = self.pad + hw / 2 dTick = px / n y = (w if self.vertical else h) // 2 - 1 for i in range(n+1): tick = round(tick0 + i * dTick) p1 = (y, tick) if self.vertical else (tick, y) p2 = (y+1, tick) if self.vertical else (tick, y+1) pygame.draw.line(img.surface, self.borderColor, p1, p2, 1) tick += dTick # Handle if self.handle: r = pygame.Rect(((0, x) + (w, hw)) if self.vertical else (x, 0) + (hw, h)) pygame.draw.rect(img.surface, self.fgColor, r) r1, r2 = r.bottomleft, r.topright if self.vertical: r1, r2 = r2, r1 pygame.draw.line(img.surface, self.borderColor, r.topleft, r1, 1) pygame.draw.line(img.surface, self.borderColor, r2, r.bottomright, 1) elif self.vertical: pygame.draw.rect(img.surface, self.fgColor, (0, x) + (w, h - x)) else: pygame.draw.rect(img.surface, self.fgColor, (0, 0) + (x, h)) # Handle centre x += hw // 2 self.handleDecor(x, img.surface, 1 if hw < 25 else 3) # Text txt = self.getValueText() if txt != None: txt = Image.text(txt, self.font, self.color) dx = hw // 2 + 8 tw = txt.width x = x - tw - dx if x + dx + tw + 4 > (h if self.vertical else w) else x + dx if self.vertical: txt = Image(pygame.transform.rotate(txt.surface, -90)) x = (0, x) else: x = (x, 0) txt.blitTo(img.surface, x) # Finish up if self.border: img.borderInPlace(self.border, self.borderColor) self.imgs = {0: img}
def image(self): "Convert to uncompressed Image" data = self.compress.decompress(self.gz) mode = self.modes[self.mode] return Image(pygame.image.fromstring(data, self.size, mode))