wand icon indicating copy to clipboard operation
wand copied to clipboard

OUTLINE missing pt.2(seeking help)

Open OilSubjectLoss7 opened this issue 2 years ago • 0 comments

Ref: https://github.com/emcconville/wand/issues/564

I think the following codes are messing with outline.

##########   main func for image rendering   ##############

def export_caption(caption, filename):
    '''Creates a .png file <filename> suitable for bdsup2sub that displays
    the given caption.'''
    img = Image(width=XSIZE, height=YSIZE)
    # by default wand will use the text's baseline as y-coord which is bad,
    # because we'd never know where we end, so set the gravity to north_west
    # Beware: it seems like if we set text_alignment='center' so we could
    # use wand's multiline text feature the gravity setting will be lost
    # irrevocably, so we need to deal with multiline captions ourselves
    img.gravity = 'north_west'
    box = Drawing()
    # Color() handles 'none' by itself, case-independently
    box.fill_color = Color(OPTS.BOXCOLOR)

    draw = Drawing()
    draw.fill_color = Color(OPTS.FILLCOLOR)
    draw.font = FONT
    draw.font_size = FONTSIZE
    draw.text_encoding = ENCODING
    if OPTS.ANTIALIASING:
        draw.text_antialias = True
    else:
        draw.text_antialias = False
    if OUTLINEWIDTH:
        draw.stroke_color = "BLACK"
        draw.stroke_width = OUTLINEWIDTH
        if OPTS.ANTIALIASING:
            draw.stroke_antialias = True
        else:
            draw.stroke_antialias = False

    lines = [line.strip() for line in caption.splitlines() if line.strip()]

    # padding for the text's bounding box
    padx, pady = BOXPADDING

    # calculate the max. allowed text width, and don't forget the outline but
    # ignore the box; keep a few extra px. (1% of XSIZE) in reserve,
    # just to be on the safe side in case we have rounding errors
    max_textwidth = int(round(XSIZE * MAXLINESIZE / 100)) - \
                    2 * OUTLINEWIDTH - int(round(0.01 * XSIZE))

    # now loop through the list of strings, calculate each string's width and
    # if necessary split it in two;
    # repeat this until no line needs to be wrapped
    lines, wmax, line_widths = fix_caption(lines, max_textwidth, img, draw)

    # collect info for which lines we need y box padding;
    # this seems useful to avoid a too big offset between text lines,
    # which may look odd, esp. when the box is transparent
    i = 0
    padinfo = []
    for lw in line_widths:
        a, b, c = 0, 0, 0 # top padding, bottom padding, Y incr. of next line
        if i == 0:
            # the first line needs top padding
            a = pady
        elif line_widths[i-1] < lw:
            # previous line is smaller, so we need top padding
            a = pady
        if i == len(line_widths) - 1:
            # the last line needs bottom padding
            b = pady
        elif line_widths[i+1] < lw:
            # next line is smaller, so we need bottom padding
            b = pady
        elif line_widths[i+1] > lw:
            # next line is bigger, shift the Y-increment by pady
            c = pady
        i += 1
        padinfo.append((a, b, c))

    # width of the box == max. textwidth + 2* (boxpad + outline width)
    wmax = wmax + 2*padx + 2*OUTLINEWIDTH

    # now all lines should be safe to fit on the screen,
    # so start drawing
    Y = 0
    i = 0
    bottom = 0
    for line in lines:
        s = line.strip()
        m = draw.get_font_metrics(img, line)
        w, h = int(m.text_width), int(m.text_height)

        # make sure the smaller line appears centered relative to the
        # bigger line
        if wmax > XSIZE:
            # may happen if an insane x box padding was given;
            # make sure the text will be centered anyway, the excess box
            # will be chopped off later
            X = int((XSIZE - w) / 2)
        else:
            X = int((wmax - w) / 2)

        a, b, c = padinfo[i]
        # draw the bounding box
        if OPTS.BOXCOLOR.lower() != 'none':
            box.rectangle(X - OUTLINEWIDTH - padx,
                          Y - OUTLINEWIDTH - a,
                          X + w + OUTLINEWIDTH + padx,
                          Y + h + OUTLINEWIDTH + b)
            box(img)

        # draw the text and shift the Y position to the correct
        # coordinate for the following line (if any)
        draw.text(X, Y, s)
        draw(img)

        # store bottom Y coord
        bottom = Y + h + OUTLINEWIDTH + b
        Y = bottom + c + OUTLINEWIDTH + 2 # 1 px. extra so the boxes won't overlap
        i += 1

    x0, y0, x1, y1 = 0, 0, wmax + 1, bottom + 1
    # cut the text box from the surrounding void
    if y1 > YSIZE:
        # may happen if the font is too big or an insane y boxpadding is set
        printerror('\nError: generated subtitle image exceeds screen height')
        printerror('The offending subtitle text was:')
        for line in caption.splitlines():
            printerror('    ' + line)
        printerror('This subtitle will not look as expected.')
        y1 = YSIZE

    if x1 > XSIZE:
        # may happen if the user set insane boxpadding values, making
        # it impossible to wrap the text to fit into one line
        printerror('\nError: generated subtitle image exceeds screen width')
        printerror('The offending subtitle text was:')
        for line in caption.splitlines():
            printerror('    ' + line)
        printerror('This subtitle may not look as expected.')
        x1 = XSIZE

    img.crop(x0, y0, x1, y1)

    # write file and return the size for our xml content
    img.format = 'png'
    img.save(filename=filename)
    box.destroy()
    draw.destroy()
    img.destroy()
    return wmax+1, bottom+1

Whole file: srt2vobsub.zip

OilSubjectLoss7 avatar Feb 28 '22 06:02 OilSubjectLoss7