예제 #1
0
 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
예제 #2
0
    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)
예제 #3
0
    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)
예제 #4
0
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
예제 #5
0
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
예제 #6
0
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