def apply_blend(self, glyphimage, previmage, image): if self.blend is not None: image = np.clip( image, 0.0, 1.0 ) image = self.blend(base=previmage, blend=image) image = fu.alpha_blend(previmage, image * self.opacity) self._verify(self.blend, image) return image
def apply(self, info, glyph, image): out = utils.maximum(image, self.kernel) if self.spread: out = fu.blur_image(out, self.spread) r, g, b, a = fu.split_channels(out) r[a > 0] = self.color[0] g[a > 0] = self.color[1] b[a > 0] = self.color[2] a[a > 0] = self.opacity return fu.alpha_blend(out, image)
def apply(self, info, glyph, image): x = int(self.offsetx) y = -int(self.offsety) shadowbitmap = np.copy( image ) shadowbitmap = np.roll(shadowbitmap, x, axis = 0) shadowbitmap = np.roll(shadowbitmap, y, axis = 1) # replace the color r, g, b, a = fu.split_channels(shadowbitmap) shadowbitmap = np.dstack( (r, g, b, a) ) * (self.color[0], self.color[1], self.color[2], self.opacity) shadowbitmap = fu.blur_image(shadowbitmap, self.size) topbitmap = np.zeros_like( shadowbitmap ) topbitmap[:image.shape[0], :image.shape[1], :] = image return fu.alpha_blend(shadowbitmap, topbitmap)
def write_text(options, info, pairkernings): """ Writes the given text to an image """ pairkernings = pairkernings or dict() # first, calculate the texture size if os.path.isfile(options.writetext): with open(options.writetext, 'rt') as f: options.writetext = f.read() cinfo = {glyph.utf8 : glyph for glyph in info.glyphs} texture_size = _calc_bbox(info, cinfo, pairkernings, options.writetext) texture_size = (texture_size[0]+info.padding*2+60, texture_size[1]+info.padding*2) ones = np.ones(texture_size, float) bgcolor = info.bgcolor if options.bgcolor: bgcolor = eval(options.bgcolor) bgcolor = map( lambda x: float(x)/255.0 if isinstance(x, int) else x, bgcolor ) if len(bgcolor) == 3: bgcolor = list(bgcolor)+[1.0] r = ones * bgcolor[0] g = ones * bgcolor[1] b = ones * bgcolor[2] a = ones * bgcolor[3] zeros = np.zeros(texture_size, float) image = np.dstack( (r,g,b,zeros) ) x = 0 y = info.ascender prevc = 0 found = False for c in options.writetext: c = ord(c) char = cinfo.get( c, None ) if not char: logging.warning("Character not in info.letters: '%s'" % unichr(c)) continue if char.bitmap == None: x += char.advance prevc = c continue found = True x += pairkernings.get( _encode_pair(prevc, c), 0) bw, bh, _ = char.bitmap.shape bx = x + char.bearingX by = y - char.bearingY # we must make sure that the first pixel is within range if bx < 0: x += -char.bearingX bx = x target = image[bx : bx + bw, by : by + bh ] try: image[bx : bx + bw, by : by + bh ] = fu.alpha_blend( target, char.bitmap ) except Exception, e: print e print 'image shape', image.shape print 'target shape', target.shape print 'bitmap shape', char.bitmap.shape print "bx, bw", bx, bw print "by, bh", by, bh print "y", y print "bearingY", char.bearingY print "lineheight", info.max_height print "c:", char.utf8, char.unicode print "" print "" raise x += char.advance prevc = c
def _apply_layers(info): #bbox = np.array( [0, 0] ) width = 0 top = 0 bottom = 0 max_bearing_y = 0 for glyph in info.glyphs: if glyph.bitmap is None: continue width = max(width, glyph.bitmap.shape[0]) top = max(top, glyph.bearingY) bottom = min(bottom, glyph.bearingY - glyph.bitmap.shape[1]) #bbox = np.maximum( bbox, glyph.bitmap.shape ) max_bearing_y = max(max_bearing_y, glyph.bearingY) bbox = np.array( [width, top - bottom] ) bbox[0] += info.extrapadding[0] + info.extrapadding[2] bbox[1] += info.extrapadding[1] + info.extrapadding[3] info.maxsize = bbox info.maxbearingY = max_bearing_y elements = [] for layer in info.layers: elements.append(layer) elements.append(layer.color) for element in elements + info.posteffects: if hasattr(element, 'set_dimensions'): element.set_dimensions(info.maxsize[0], info.maxsize[1]) for glyph in info.glyphs: if glyph.bitmap is None: continue glyphimage = glyph.bitmap glyphimage.flags.writeable = False # ???? fonteffects.DefaultMask.idx = np.where(glyphimage == 0) previmage = np.dstack((glyphimage, glyphimage, glyphimage, glyphimage)) previmage.flags.writeable = False previmage = _apply_layer(info, glyph, info.layers[0], previmage, glyphimage) previmage.flags.writeable = False for layer in info.layers[1:]: previmage = _apply_layer(info, glyph, layer, previmage, glyphimage) previmage.flags.writeable = False for effect in info.posteffects: previmage = effect.apply(info, glyph, previmage) previmage.flags.writeable = False bgimage = np.ones( previmage.shape, float) * (info.bgcolor[0], info.bgcolor[1], info.bgcolor[2], 0.0) bgimage.flags.writeable = False previmage = fu.alpha_blend(bgimage, previmage) previmage.flags.writeable = False glyph.bitmap = previmage
def render(info): """ Assuming (0,0) is at the top left corner of the image. :param info: The settings from the fontinfo file :return: The image all glyphs are rendered to """ # sort the glyphs info.glyphs.sort(cmp=_glyph_cmp) # Work in progress #iw, ih = _guess_dimensions(info.glyphs) iw, ih = info.texturesize #ih /= 2 #print "guessed image size", iw, ih image = _create_image(info, iw, ih) textureoffset = info.textureoffset padding = info.padding packer = binpack.create_packer(binpack.SKYLINE_BL, iw - textureoffset[0], ih - textureoffset[1], False) # DEBUG PACK RENDERING if DEBUG: image[:, :, 0] = 1.0 image[:, :, 3] = 1.0 for glyph in info.glyphs: if glyph.bitmap is None: continue bitmap = glyph.bitmap w, h, d = bitmap.shape rect = binpack.pack_rect(packer, w + padding, h + padding) if rect.height == 0: raise FontException("The texture size is too small: (%d, %d) Increase the 'texturesize' property in the font info" % (info.texturesize[0], info.texturesize[1]) ) rect.x += textureoffset[0] rect.y += textureoffset[1] rect.width -= padding rect.height -= padding glyph.bitmapbox = (rect.x, rect.y, rect.width, rect.height) # check if the glyph has been flipped if w != h and w == rect.height: bitmap = np.rot90(bitmap) try: image[ rect.x : rect.x + rect.width, rect.y : rect.y + rect.height ] = bitmap # DEBUG PACK RENDERING if DEBUG: import fontutils top = image[ rect.x : rect.x + rect.width, rect.y : rect.y + rect.height ] ones = np.ones( (top.shape[0], top.shape[1]) ) from random import random r = random() * 0.4 + 0.6 g = random() * 0.4 + 0.6 b = random() * 0.4 + 0.6 a = 1.0 bottom = np.dstack( (ones * r, ones * g, ones * b, ones * a) ) result = fontutils.alpha_blend(bottom, top) image[ rect.x : rect.x + rect.width, rect.y : rect.y + rect.height ] = result except Exception, e: print "ERROR", e print "RECT", rect #print "bmshape", (bx,by,w,h) print "image.shape", image.shape print "char.bitmap.shape", glyph.bitmap.shape raise